diff --git a/.editorconfig b/.editorconfig
index bfeab8c84f..4167733d05 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -199,6 +199,18 @@ dotnet_diagnostic.AVP1032.severity = warning
dotnet_diagnostic.AVP1040.severity = warning
dotnet_diagnostic.AVA2001.severity = warning
+# Avalonia property source generator (GeneratedPropertyAnalyzer)
+dotnet_diagnostic.AVP2001.severity = error
+dotnet_diagnostic.AVP2002.severity = error
+dotnet_diagnostic.AVP2003.severity = error
+dotnet_diagnostic.AVP2004.severity = error
+dotnet_diagnostic.AVP2005.severity = error
+dotnet_diagnostic.AVP2006.severity = error
+dotnet_diagnostic.AVP2007.severity = error
+dotnet_diagnostic.AVP2008.severity = error
+dotnet_diagnostic.AVP2100.severity = warning
+dotnet_diagnostic.AVP2101.severity = warning
+
# Xaml files
[*.{xaml,axaml}]
indent_size = 2
diff --git a/.ncrunch/Avalonia.Controls.ColorPicker.v3.ncrunchproject b/.ncrunch/Avalonia.Controls.ColorPicker.v3.ncrunchproject
new file mode 100644
index 0000000000..0bcc569d05
--- /dev/null
+++ b/.ncrunch/Avalonia.Controls.ColorPicker.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ False
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.DBus.Generators.v3.ncrunchproject b/.ncrunch/Avalonia.DBus.Generators.v3.ncrunchproject
new file mode 100644
index 0000000000..08b7dfa6ee
--- /dev/null
+++ b/.ncrunch/Avalonia.DBus.Generators.v3.ncrunchproject
@@ -0,0 +1,8 @@
+
+
+
+ TargetFramework = netstandard2.0
+
+ False
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.FreeDesktop.AtSpi.v3.ncrunchproject b/.ncrunch/Avalonia.FreeDesktop.AtSpi.v3.ncrunchproject
new file mode 100644
index 0000000000..0bcc569d05
--- /dev/null
+++ b/.ncrunch/Avalonia.FreeDesktop.AtSpi.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ False
+
+
\ No newline at end of file
diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
index 2d66481319..bf7554a66d 100644
--- a/Avalonia.Desktop.slnf
+++ b/Avalonia.Desktop.slnf
@@ -55,6 +55,7 @@
"src\\Windows\\Avalonia.Win32.Automation\\Avalonia.Win32.Automation.csproj",
"src\\Windows\\Avalonia.Win32.Interoperability\\Avalonia.Win32.Interoperability.csproj",
"src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
+ "tests\\Avalonia.Analyzers.Tests\\Avalonia.Analyzers.Tests.csproj",
"tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj",
"tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj",
"tests\\Avalonia.Build.Tasks.UnitTest\\Avalonia.Build.Tasks.UnitTest.csproj",
diff --git a/Avalonia.slnx b/Avalonia.slnx
index d902fabe98..9da4ac18a9 100644
--- a/Avalonia.slnx
+++ b/Avalonia.slnx
@@ -137,6 +137,7 @@
+
diff --git a/Directory.Build.props b/Directory.Build.props
index 931a386d31..a602c6015e 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -4,6 +4,7 @@
$(MSBuildThisFileDirectory)build-intermediate/nuget
$(MSBuildThisFileDirectory)\src\tools\Avalonia.Designer.HostApp\bin\$(Configuration)\$(AvsCurrentTargetFramework)\Avalonia.Designer.HostApp.dll
+ $(MSBuildThisFileDirectory)\build\Assets\
false
False
diff --git a/Directory.Packages.props b/Directory.Packages.props
index d38cb33b28..3f4de3371d 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -6,7 +6,7 @@
-
+
@@ -23,6 +23,9 @@
+
+
+
@@ -69,6 +72,7 @@
+
@@ -78,4 +82,4 @@
-
\ No newline at end of file
+
diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index 5c720c9413..1dda132a59 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -1,4 +1,4 @@
-
+
@@ -145,6 +145,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
current/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
+
+ CP0006
+ E:Avalonia.Platform.IPlatformSettings.PreferredApplicationLanguageChanged
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0006
M:Avalonia.Platform.IBitmapImpl.Save(System.IO.Stream,Avalonia.Media.Imaging.BitmapEncoderOptions)
@@ -175,6 +181,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0006
+ P:Avalonia.Platform.IPlatformSettings.PreferredApplicationLanguage
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0006
M:Avalonia.Controls.Platform.IWin32OptionsTopLevelImpl.SetWindowCornerPreference(Avalonia.Controls.Win32Properties.WindowCornerPreference)
@@ -193,6 +205,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+ CP0006
+ E:Avalonia.Platform.IPlatformSettings.PreferredApplicationLanguageChanged
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0006
M:Avalonia.Platform.IBitmapImpl.Save(System.IO.Stream,Avalonia.Media.Imaging.BitmapEncoderOptions)
@@ -223,6 +241,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0006
+ P:Avalonia.Platform.IPlatformSettings.PreferredApplicationLanguage
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0006
M:Avalonia.Controls.Platform.IWin32OptionsTopLevelImpl.SetWindowCornerPreference(Avalonia.Controls.Win32Properties.WindowCornerPreference)
@@ -241,4 +265,4 @@
baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
current/Avalonia/lib/net8.0/Avalonia.Controls.dll
-
\ No newline at end of file
+
diff --git a/build/Assets/Icon.png b/build/Assets/Icon.png
index 41a2a618fb..54fe581f21 100644
Binary files a/build/Assets/Icon.png and b/build/Assets/Icon.png differ
diff --git a/build/Assets/icon-32.png b/build/Assets/icon-32.png
new file mode 100644
index 0000000000..f8afccc962
Binary files /dev/null and b/build/Assets/icon-32.png differ
diff --git a/build/Assets/icon.ico b/build/Assets/icon.ico
new file mode 100644
index 0000000000..b5ce607b0e
Binary files /dev/null and b/build/Assets/icon.ico differ
diff --git a/build/Assets/icon.svg b/build/Assets/icon.svg
new file mode 100644
index 0000000000..d5e1dcbf61
--- /dev/null
+++ b/build/Assets/icon.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 2a4e07c3d2..c4c914fb49 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -10,7 +10,7 @@
true
$(NoWarn);CS1591;NU5104
MIT
- Icon.png
+ icon.png
Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS and with experimental support for Android, iOS and WebAssembly.
avalonia;avaloniaui;mvvm;rx;reactive extensions;android;ios;mac;forms;wpf;net;netstandard;net461;uwp;xamarin
https://github.com/AvaloniaUI/Avalonia/releases
@@ -20,6 +20,6 @@
-
+
diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm
index d4ab79bc47..805cd7ee02 100644
--- a/native/Avalonia.Native/src/OSX/AvnView.mm
+++ b/native/Avalonia.Native/src/OSX/AvnView.mm
@@ -4,6 +4,7 @@
//
#import
+#import /* For the TIS functions used to classify the keyboard input source. */
#include "AvnView.h"
#include "automation.h"
#import "WindowInterfaces.h"
@@ -22,8 +23,9 @@
NSMutableAttributedString* _text;
NSRange _selectedRange;
NSRange _markedRange;
- NSEvent* _lastKeyDownEvent;
NSMutableArray* _accessibilityChildren;
+ NSString* _keyboardInputSourceId;
+ bool _keyboardInputSourceComposes;
}
- (void)onClosed
@@ -649,9 +651,100 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
[super flagsChanged:event];
}
-- (bool) handleKeyDown: (NSTimeInterval) timestamp withKey:(AvnKey)key withPhysicalKey:(AvnPhysicalKey)physicalKey withModifiers:(AvnInputModifiers)modifiers withKeySymbol:(NSString*)keySymbol {
- auto parent = _parent.tryGet();
- return parent->TopLevelEvents->RawKeyEvent(KeyDown, timestamp, modifiers, key, physicalKey, [keySymbol UTF8String]);
+// The input mode an input method uses for direct alphanumeric typing. In this mode the input
+// method passes keys straight through instead of composing, so keys must not be masked.
+static CFStringRef const AlphanumericInputModeId = CFSTR("com.apple.inputmethod.Roman");
+
+static bool InputSourceComposes(TISInputSourceRef source)
+{
+ // A plain keyboard layout never composes. Dead keys are not driven by the input source, they
+ // show up as a composition in progress and are covered by hasMarkedText.
+ auto type = static_cast(TISGetInputSourceProperty(source, kTISPropertyInputSourceType));
+
+ if(type == nullptr || CFEqual(type, kTISTypeKeyboardLayout))
+ {
+ return false;
+ }
+
+ auto mode = static_cast(TISGetInputSourceProperty(source, kTISPropertyInputModeID));
+
+ return mode == nullptr || !CFEqual(mode, AlphanumericInputModeId);
+}
+
+// Whether this keystroke could be the one that starts a composition. Only a key that produces a
+// printable character can, and masking any of the others would stop controls like TextBox from
+// reacting to them at all.
+static bool CanStartComposition(NSString* keySymbol, NSEventModifierFlags modifierFlags)
+{
+ // No symbol at all: the arrows, the function keys, Home, End and friends.
+ if(keySymbol == nullptr || [keySymbol length] == 0)
+ {
+ return false;
+ }
+
+ // KeySymbolFromScanCode deliberately reports the control character for Backspace, Enter, Tab
+ // and Escape, and Forward Delete reports DEL (0x7F), so a symbol alone does not mean the key
+ // produces text. Those keys edit or cancel, they never start a composition.
+ auto firstChar = [keySymbol characterAtIndex:0];
+
+ if(firstChar < 0x20 || firstChar == 0x7F)
+ {
+ return false;
+ }
+
+ // Command and Control combinations are shortcuts, which an input method does not consume.
+ return (modifierFlags & (NSEventModifierFlagCommand | NSEventModifierFlagControl)) == 0;
+}
+
+// Returns true when the input source with the given id is an input method that can start a
+// composition, as opposed to a plain keyboard layout or an input method in alphanumeric mode.
+static bool KeyboardInputSourceComposes(NSString* sourceId)
+{
+ NSDictionary* filter = @{ (__bridge NSString*)kTISPropertyInputSourceID: sourceId };
+
+ // Include every installed source, not just the enabled ones: an input method mode can be
+ // selected without being listed as enabled, and failing to find it would classify a
+ // composing input method as a plain layout.
+ auto sources = TISCreateInputSourceList((__bridge CFDictionaryRef)filter, true);
+
+ if(sources == nullptr)
+ {
+ return false;
+ }
+
+ auto composes = CFArrayGetCount(sources) > 0 &&
+ InputSourceComposes((TISInputSourceRef)CFArrayGetValueAtIndex(sources, 0));
+
+ CFRelease(sources);
+
+ return composes;
+}
+
+// Whether the currently selected keyboard input source is a composing input method. The result
+// is cached per input source id, since this is queried for every key down.
+- (bool)isComposingInputSourceSelected
+{
+ auto inputContext = [self inputContext];
+
+ if(inputContext == nullptr)
+ {
+ return false;
+ }
+
+ NSString* sourceId = [inputContext selectedKeyboardInputSource];
+
+ if(sourceId == nullptr)
+ {
+ return false;
+ }
+
+ if(![sourceId isEqualToString:_keyboardInputSourceId])
+ {
+ _keyboardInputSourceId = sourceId;
+ _keyboardInputSourceComposes = KeyboardInputSourceComposes(sourceId);
+ }
+
+ return _keyboardInputSourceComposes;
}
- (void)keyDown:(NSEvent *)event
@@ -661,57 +754,57 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
{
return;
}
-
- _lastKeyDownEvent = event;
-
+
auto timestamp = static_cast([event timestamp] * 1000);
-
+
auto scanCode = [event keyCode];
- auto key = VirtualKeyFromScanCode(scanCode, [event modifierFlags]);
auto physicalKey = PhysicalKeyFromScanCode(scanCode);
auto keySymbol = KeySymbolFromScanCode(scanCode, [event modifierFlags]);
-
+ auto keySymbolUtf8 = keySymbol == nullptr ? nullptr : [keySymbol UTF8String];
+
auto modifiers = [self getModifiers:[event modifierFlags]];
-
- //InputMethod is active
- if(parent->InputMethod->IsActive()){
- auto hasInputModifier = modifiers != AvnInputModifiersNone;
-
- //Handle keyDown first if an input modifier is present
- if(hasInputModifier){
- if([self handleKeyDown:timestamp withKey:key withPhysicalKey:physicalKey withModifiers:modifiers withKeySymbol:keySymbol]){
- //User code has handled the event
- _lastKeyDownEvent = nullptr;
-
- return;
- }
- }
-
- if([[self inputContext] handleEvent:event] == NO){
- //KeyDown has not been consumed by the input context
-
- //Only raise a keyDown if we don't have a modifier
- if(!hasInputModifier){
- [self handleKeyDown:timestamp withKey:key withPhysicalKey:physicalKey withModifiers:modifiers withKeySymbol:keySymbol];
- }
- }
-
+
+ // The keystroke belongs to the input method when a composition is already in progress, since
+ // it then selects a candidate, commits or cancels it. It also belongs to the input method
+ // when a character key is typed into a text input client while a composing input method is
+ // selected, because that keystroke may be the one that starts the composition and we cannot
+ // know that before the input context has seen it.
+ //
+ // In both cases mask the key the way Win32 reports VK_PROCESSKEY, so that user code still
+ // observes a KeyDown but no KeyGesture can match it. The physical key and the key symbol
+ // keep their real values, so the underlying key remains recoverable.
+ //
+ // Both cases require an active client: without one the input context is never consulted, so
+ // marked text left over from a composition that lost its client mid-way must not mask keys.
+ auto imeProcessed = parent->InputMethod->IsActive() &&
+ ([self hasMarkedText] ||
+ (CanStartComposition(keySymbol, [event modifierFlags]) &&
+ [self isComposingInputSourceSelected]));
+
+ auto key = imeProcessed
+ ? AvnKeyImeProcessed
+ : VirtualKeyFromScanCode(scanCode, [event modifierFlags]);
+
+ // A KeyDown is always raised before the input context sees the event, otherwise the
+ // input context silently consumes printable keys (space, letters, digits) and user code
+ // never gets a chance to react to them.
+ auto handled = parent->TopLevelEvents->RawKeyEvent(KeyDown, timestamp, modifiers, key, physicalKey, keySymbolUtf8);
+
+ if(handled)
+ {
+ // User code has handled the event, so no text may be produced from it.
+ return;
}
- //InputMethod not active
- else{
- auto keyDownHandled = [self handleKeyDown:timestamp withKey:key withPhysicalKey:physicalKey withModifiers:modifiers withKeySymbol:keySymbol];
-
- //Raise text input event for unhandled key down
- if(!keyDownHandled){
- if(keySymbol != nullptr && key != AvnKeyEnter){
- auto timestamp = static_cast([event timestamp] * 1000);
-
- parent->TopLevelEvents->RawTextInputEvent(timestamp, [keySymbol UTF8String]);
- }
- }
+
+ if(parent->InputMethod->IsActive())
+ {
+ // Let the input context produce the text or drive the composition.
+ [[self inputContext] handleEvent:event];
+ }
+ else if(keySymbol != nullptr && key != AvnKeyEnter)
+ {
+ parent->TopLevelEvents->RawTextInputEvent(timestamp, keySymbolUtf8);
}
-
- _lastKeyDownEvent = nullptr;
}
- (void)keyUp:(NSEvent *)event
@@ -721,9 +814,9 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
}
- (void) doCommandBySelector:(SEL)selector{
- if(_lastKeyDownEvent != nullptr){
- [self keyboardEvent:_lastKeyDownEvent withType:KeyDown];
- }
+ // -keyDown: already raised a KeyDown for this event before handing it to the input
+ // context, so nothing is left to do here. The method still has to be implemented:
+ // falling back to NSResponder would perform the default action and emit a system beep.
}
- (AvnInputModifiers)getModifiers:(NSEventModifierFlags)mod
diff --git a/native/Avalonia.Native/src/OSX/PlatformSettings.mm b/native/Avalonia.Native/src/OSX/PlatformSettings.mm
index 34ceb93186..d30d55e2ec 100644
--- a/native/Avalonia.Native/src/OSX/PlatformSettings.mm
+++ b/native/Avalonia.Native/src/OSX/PlatformSettings.mm
@@ -1,12 +1,19 @@
#include "common.h"
+#include "AvnString.h"
@interface CocoaThemeObserver : NSObject
-(id)initWithCallback:(IAvnActionCallback *)callback;
@end
+@interface CocoaLocaleObserver : NSObject
+-(id)initWithCallback:(IAvnActionCallback *)callback;
+-(void)localeDidChange:(NSNotification *)notification;
+@end
+
class PlatformSettings : public ComSingleObject
{
CocoaThemeObserver* observer;
+ CocoaLocaleObserver* localeObserver;
public:
FORWARD_IUNKNOWN()
@@ -58,6 +65,28 @@ public:
[[NSApplication sharedApplication] addObserver:observer forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nil];
}
}
+
+ virtual HRESULT GetPreferredLanguage(IAvnString** ret) override
+ {
+ @autoreleasepool
+ {
+ if (ret == nullptr)
+ return E_POINTER;
+
+ auto language = [[NSLocale preferredLanguages] firstObject];
+ *ret = language == nil ? nullptr : CreateAvnString(language);
+ return S_OK;
+ }
+ }
+
+ virtual void RegisterLanguageChange(IAvnActionCallback *callback) override
+ {
+ localeObserver = [[CocoaLocaleObserver alloc] initWithCallback: callback];
+ [[NSNotificationCenter defaultCenter] addObserver:localeObserver
+ selector:@selector(localeDidChange:)
+ name:NSCurrentLocaleDidChangeNotification
+ object:nil];
+ }
private:
unsigned int to_argb(NSColor* color)
@@ -107,6 +136,23 @@ private:
}
@end
+@implementation CocoaLocaleObserver
+{
+ ComPtr _callback;
+}
+- (id) initWithCallback:(IAvnActionCallback *)callback {
+ self = [super init];
+ if (self) {
+ _callback = callback;
+ }
+ return self;
+}
+
+- (void)localeDidChange:(NSNotification *)notification {
+ _callback->Run();
+}
+@end
+
extern IAvnPlatformSettings* CreatePlatformSettings()
{
return new PlatformSettings();
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
index 33ab1529fc..205f1efbdf 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
@@ -465,11 +465,21 @@ void WindowBaseImpl::CleanNSWindow() {
}
void WindowBaseImpl::CreateNSWindow(bool usePanel) {
+ // Anchor the content rect to the primary screen's origin. It's usually at (0,0), but can be offset while the
+ // display server is mid-reconfiguration. This ensures the window is always on a proper screen.
+ // See https://github.com/AvaloniaUI/Avalonia/issues/18895
+ NSPoint origin = NSZeroPoint;
+ NSArray* screens = [NSScreen screens];
+ if (screens.count > 0)
+ origin = screens.firstObject.frame.origin;
+
+ NSRect contentRect = NSRect { origin.x, origin.y, lastSize };
+
if (usePanel) {
- Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
+ Window = [[AvnPanel alloc] initWithParent:this contentRect:contentRect styleMask:NSWindowStyleMaskBorderless];
[Window setHidesOnDeactivate:false];
} else {
- Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
+ Window = [[AvnWindow alloc] initWithParent:this contentRect:contentRect styleMask:NSWindowStyleMaskBorderless];
}
}
diff --git a/packages/Avalonia/AvaloniaRules.Project.xml b/packages/Avalonia/AvaloniaRules.Project.xml
index 0a5c1b8243..120cc1c255 100644
--- a/packages/Avalonia/AvaloniaRules.Project.xml
+++ b/packages/Avalonia/AvaloniaRules.Project.xml
@@ -5,6 +5,7 @@
+
@@ -139,4 +140,11 @@ Example: MyApp.Presentation.*, MyApp.Presentation.Views;MyApp.Presentation.Contr
+
+
+
+
diff --git a/readme.md b/readme.md
index 9ed6c59f90..e291498703 100644
--- a/readme.md
+++ b/readme.md
@@ -10,7 +10,7 @@
Considered by many to be the spiritual successor to WPF, Avalonia UI provides a familiar, modern development experience for XAML developers creating cross-platform applications. While Avalonia UI is [similar to WPF](https://docs.avaloniaui.net/docs/next/get-started/wpf/), it isn't a 1:1 copy, and you'll find plenty of improvements.
-For those seeking a cross-platform WPF, we have created [Avalonia XPF]([https://avaloniaui.net/xpf](https://avaloniaui.net/xpf?utm_source=github&utm_medium=referral&utm_content=readme_link)), enabling WPF applications to run on macOS and Linux with little to no code changes. Avalonia XPF is a commercial product and is licensed per-app, per-platform.
+For those seeking a cross-platform WPF, we have created [Avalonia XPF](https://avaloniaui.net/xpf?utm_source=github&utm_medium=referral&utm_content=readme_link), enabling WPF applications to run on macOS and Linux with little to no code changes. Avalonia XPF is a commercial product and is licensed per-app, per-platform.
### Blog
To see the latest announcements and read about the state of Avalonia, check out the [Avalonia UI Blog](https://www.avaloniaui.net/blog?utm_source=github&utm_medium=referral&utm_content=readme_link).
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 978eb361c4..a1e9b45c2c 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -9,8 +9,8 @@
apk
-
- Resources\drawable\Icon.png
+
+ Resources\drawable\icon.png
diff --git a/samples/ControlCatalog.Browser/wwwroot/favicon.ico b/samples/ControlCatalog.Browser/wwwroot/favicon.ico
index da8d49ff9b..b5ce607b0e 100644
Binary files a/samples/ControlCatalog.Browser/wwwroot/favicon.ico and b/samples/ControlCatalog.Browser/wwwroot/favicon.ico differ
diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
index 779e9b3462..4fe7c499fb 100644
--- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
+++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
@@ -6,6 +6,7 @@
true
true
true
+ $(SharedAssetsPath)\icon.ico
@@ -35,6 +36,7 @@
app.manifest
+
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index 42f35c7205..336eae7553 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -74,7 +74,7 @@
-
+
@@ -83,7 +83,7 @@
-
+
diff --git a/samples/ControlCatalog/Assets/Icon.png b/samples/ControlCatalog/Assets/Icon.png
deleted file mode 100644
index 41a2a618fb..0000000000
Binary files a/samples/ControlCatalog/Assets/Icon.png and /dev/null differ
diff --git a/samples/ControlCatalog/Assets/avalonia-32.png b/samples/ControlCatalog/Assets/avalonia-32.png
deleted file mode 100644
index 7b443e7a25..0000000000
Binary files a/samples/ControlCatalog/Assets/avalonia-32.png and /dev/null differ
diff --git a/samples/ControlCatalog/Assets/banner-bg.png b/samples/ControlCatalog/Assets/banner-bg.png
new file mode 100644
index 0000000000..0ad18f2cc4
Binary files /dev/null and b/samples/ControlCatalog/Assets/banner-bg.png differ
diff --git a/samples/ControlCatalog/Assets/banner-logo.png b/samples/ControlCatalog/Assets/banner-logo.png
new file mode 100644
index 0000000000..48e825d993
Binary files /dev/null and b/samples/ControlCatalog/Assets/banner-logo.png differ
diff --git a/samples/ControlCatalog/Assets/logo1.png b/samples/ControlCatalog/Assets/logo1.png
new file mode 100644
index 0000000000..93164bfe1e
Binary files /dev/null and b/samples/ControlCatalog/Assets/logo1.png differ
diff --git a/samples/ControlCatalog/Assets/logo2.png b/samples/ControlCatalog/Assets/logo2.png
new file mode 100644
index 0000000000..6e5e63c0ee
Binary files /dev/null and b/samples/ControlCatalog/Assets/logo2.png differ
diff --git a/samples/ControlCatalog/Assets/logo3.png b/samples/ControlCatalog/Assets/logo3.png
new file mode 100644
index 0000000000..53331bf02e
Binary files /dev/null and b/samples/ControlCatalog/Assets/logo3.png differ
diff --git a/samples/ControlCatalog/Assets/logo4.png b/samples/ControlCatalog/Assets/logo4.png
new file mode 100644
index 0000000000..930046865a
Binary files /dev/null and b/samples/ControlCatalog/Assets/logo4.png differ
diff --git a/samples/ControlCatalog/Assets/test_icon.ico b/samples/ControlCatalog/Assets/test_icon.ico
deleted file mode 100644
index da8d49ff9b..0000000000
Binary files a/samples/ControlCatalog/Assets/test_icon.ico and /dev/null differ
diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 0cc232bfe2..b2900f8dbe 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -4,6 +4,7 @@
true
true
+
%(Filename)
@@ -11,23 +12,13 @@
Designer
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
diff --git a/samples/ControlCatalog/Converter/FlexDemoNumberToThicknessConverter.cs b/samples/ControlCatalog/Converter/FlexDemoNumberToThicknessConverter.cs
new file mode 100644
index 0000000000..c5c3e0e2ed
--- /dev/null
+++ b/samples/ControlCatalog/Converter/FlexDemoNumberToThicknessConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Globalization;
+using Avalonia;
+using Avalonia.Data.Converters;
+
+namespace ControlCatalog.Converter
+{
+ internal sealed class FlexDemoNumberToThicknessConverter : IValueConverter
+ {
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is int x && targetType.IsAssignableFrom(typeof(Thickness)))
+ {
+ var y = 16 + 2 * ((x * 5) % 9);
+ return new Thickness(2 * y, y);
+ }
+
+ throw new NotSupportedException();
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
+ throw new NotSupportedException();
+ }
+}
diff --git a/samples/ControlCatalog/Icons.cs b/samples/ControlCatalog/Icons.cs
index 58d0e0b7d4..5f99bdc877 100644
--- a/samples/ControlCatalog/Icons.cs
+++ b/samples/ControlCatalog/Icons.cs
@@ -190,5 +190,8 @@ namespace ControlCatalog
// Slider tune/adjust
public const string Tune = "M3,17V19H9V17H3M3,5V7H13V5H3M13,21V19H21V17H13V15H11V21H13M7,9V11H3V13H7V15H9V9H7M21,13V11H11V13H21M15,9H17V7H21V5H17V3H15V9Z";
+
+ // Home
+ public const string Home = "M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z";
}
}
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index f7b2658b0f..08f47ca630 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -2,10 +2,8 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ControlCatalog"
- xmlns:controls="using:ControlSamples"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:models="using:ControlCatalog.Models"
- xmlns:pages="using:ControlCatalog.Pages"
xmlns:viewModels="using:ControlCatalog.ViewModels"
d:DesignWidth="1200"
d:DesignHeight="720"
@@ -45,7 +43,7 @@
ItemContainerTheme="{StaticResource NavHeaderItem}"
SelectedIndex="{Binding SelectedPageIndex}">
-
+
-
-
+
+
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index d4a45a127d..8d4da7fec2 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -2,6 +2,7 @@ using System;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Styling;
@@ -199,5 +200,10 @@ namespace ControlCatalog
ViewModel.SelectedPageIndex = 0;
}
+
+ private async void AvaloniaIcon_OnTapped(object? sender, TappedEventArgs e)
+ {
+ await TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(new Uri("https://avaloniaui.net/"));
+ }
}
}
diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml
index d839689db7..82478ebdd0 100644
--- a/samples/ControlCatalog/MainWindow.xaml
+++ b/samples/ControlCatalog/MainWindow.xaml
@@ -1,8 +1,6 @@
@@ -19,7 +18,7 @@
-
+
diff --git a/samples/ControlCatalog/Models/HomeSection.cs b/samples/ControlCatalog/Models/HomeSection.cs
new file mode 100644
index 0000000000..a7c3bdeee3
--- /dev/null
+++ b/samples/ControlCatalog/Models/HomeSection.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using ControlCatalog.ViewModels;
+
+namespace ControlCatalog.Models;
+
+public class HomeSection(string title, IReadOnlyList items)
+{
+ public string Title { get; } = title;
+ public IReadOnlyList Items { get; } = items;
+}
diff --git a/samples/ControlCatalog/Models/PageItem.cs b/samples/ControlCatalog/Models/PageItem.cs
new file mode 100644
index 0000000000..af8a361101
--- /dev/null
+++ b/samples/ControlCatalog/Models/PageItem.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Globalization;
+using System.Text;
+using Avalonia.Controls;
+using Avalonia.Media;
+
+namespace ControlCatalog.Models;
+
+public class PageItem(string header, Func factory, StreamGeometry iconData, string description, string section)
+{
+ public string Header { get; } = header;
+ public StreamGeometry? IconData { get; } = iconData;
+ public string? Description { get; } = description;
+ private string SearchKey { get; } = CreateSearchKey(header, section);
+
+ public bool IsVisible { get; set; } = true;
+
+ public Page CreatePage() => factory();
+
+ public bool MatchesSearch(string searchKey)
+ {
+ return SearchKey.Contains(searchKey, StringComparison.Ordinal);
+ }
+
+ public static string CreateSearchKey(params ReadOnlySpan values)
+ {
+ var builder = new StringBuilder(256);
+
+ foreach (var value in values)
+ {
+ var normalizedValue = value.Normalize(NormalizationForm.FormKD);
+
+ foreach (var c in normalizedValue)
+ {
+ var category = CharUnicodeInfo.GetUnicodeCategory(c);
+
+ if (category is UnicodeCategory.NonSpacingMark or
+ UnicodeCategory.SpacingCombiningMark or
+ UnicodeCategory.EnclosingMark)
+ {
+ continue;
+ }
+
+ if (char.IsLetterOrDigit(c))
+ {
+ builder.Append(char.ToUpperInvariant(c));
+ }
+ }
+ }
+
+ return builder.ToString();
+ }
+}
diff --git a/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
index 769dbc0dac..c00af6c801 100644
--- a/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
+++ b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
@@ -49,6 +49,9 @@
+
+
+
diff --git a/samples/ControlCatalog/Pages/CalendarPage.xaml b/samples/ControlCatalog/Pages/CalendarPage.xaml
index 99727e9124..44ab767dea 100644
--- a/samples/ControlCatalog/Pages/CalendarPage.xaml
+++ b/samples/ControlCatalog/Pages/CalendarPage.xaml
@@ -48,6 +48,17 @@
+
+
+
+
+ #
+
+
+
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index 149fd73d0a..db29ecbf3e 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -103,7 +103,7 @@
WrapSelection="{Binding WrapSelection}"
ItemsSource="{Binding Values}"
DisplayMemberBinding="{Binding Name}"
- TextSearch.TextBinding="{Binding SearchText, DataType=viewModels:IdAndName}" />
+ TextSearch.TextBinding="{Binding SearchText, x:DataType=viewModels:IdAndName}" />
diff --git a/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs b/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs
index 782435ae06..278899cd2f 100644
--- a/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs
+++ b/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs
@@ -11,31 +11,25 @@ using Avalonia.Controls.Shapes;
namespace ControlCatalog.Pages
{
- public class CustomDrawingExampleControl : Control
+ public partial class CustomDrawingExampleControl : Control
{
private Point _cursorPoint;
+ private Geometry _smileGeometry;
-
- public static readonly StyledProperty ScaleProperty = AvaloniaProperty.Register(nameof(Scale), 1.0d);
- public double Scale { get => GetValue(ScaleProperty); set => SetValue(ScaleProperty, value); }
-
- public static readonly StyledProperty RotationProperty = AvaloniaProperty.Register(nameof(Rotation),
- coerce: (_, val) => val % (Math.PI * 2));
+ [GeneratedStyledProperty(DefaultValue = 1.0d)]
+ public partial double Scale { get; set; }
///
/// Rotation, measured in Radians!
///
- public double Rotation
- {
- get => GetValue(RotationProperty);
- set => SetValue(RotationProperty, value);
- }
+ [GeneratedStyledProperty(CoerceMethodName = nameof(CoerceRotation))]
+ public partial double Rotation { get; set; }
- public static readonly StyledProperty ViewportCenterYProperty = AvaloniaProperty.Register(nameof(ViewportCenterY), 0.0d);
- public double ViewportCenterY { get => GetValue(ViewportCenterYProperty); set => SetValue(ViewportCenterYProperty, value); }
+ [GeneratedStyledProperty]
+ public partial double ViewportCenterY { get; set; }
- public static readonly StyledProperty ViewportCenterXProperty = AvaloniaProperty.Register(nameof(ViewportCenterX), 0.0d);
- public double ViewportCenterX { get => GetValue(ViewportCenterXProperty); set => SetValue(ViewportCenterXProperty, value); }
+ [GeneratedStyledProperty]
+ public partial double ViewportCenterX { get; set; }
private IPen _pen;
@@ -66,7 +60,7 @@ namespace ControlCatalog.Pages
_smileGeometry = sg.Clone();
}
- private Geometry _smileGeometry;
+ private static double CoerceRotation(AvaloniaObject sender, double value) => value % (Math.PI * 2);
protected override void OnPointerMoved(PointerEventArgs e)
{
diff --git a/samples/ControlCatalog/Pages/FlexPage.axaml b/samples/ControlCatalog/Pages/FlexPage.axaml
new file mode 100644
index 0000000000..bd923486e1
--- /dev/null
+++ b/samples/ControlCatalog/Pages/FlexPage.axaml
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/FlexPage.axaml.cs b/samples/ControlCatalog/Pages/FlexPage.axaml.cs
new file mode 100644
index 0000000000..397def77ae
--- /dev/null
+++ b/samples/ControlCatalog/Pages/FlexPage.axaml.cs
@@ -0,0 +1,37 @@
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using ControlCatalog.ViewModels;
+
+namespace ControlCatalog.Pages
+{
+ public partial class FlexPage : ContentPage
+ {
+ public FlexPage()
+ {
+ InitializeComponent();
+
+ DataContext = new FlexViewModel();
+ }
+
+ private void OnItemTapped(object? sender, RoutedEventArgs e)
+ {
+ if (sender is ListBoxItem control && DataContext is FlexViewModel vm && control.DataContext is FlexItemViewModel item)
+ {
+ if (vm.SelectedItem != null)
+ {
+ vm.SelectedItem.IsSelected = false;
+ }
+
+ if (vm.SelectedItem == item)
+ {
+ vm.SelectedItem = null;
+ }
+ else
+ {
+ vm.SelectedItem = item;
+ vm.SelectedItem.IsSelected = true;
+ }
+ }
+ }
+ }
+}
diff --git a/samples/ControlCatalog/Pages/HomePage.xaml b/samples/ControlCatalog/Pages/HomePage.xaml
new file mode 100644
index 0000000000..03c825c2f6
--- /dev/null
+++ b/samples/ControlCatalog/Pages/HomePage.xaml
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/HomePage.xaml.cs b/samples/ControlCatalog/Pages/HomePage.xaml.cs
new file mode 100644
index 0000000000..d2172d3012
--- /dev/null
+++ b/samples/ControlCatalog/Pages/HomePage.xaml.cs
@@ -0,0 +1,82 @@
+using System;
+using Avalonia;
+using Avalonia.Animation;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Media;
+using Avalonia.Styling;
+
+namespace ControlCatalog.Pages;
+
+public partial class HomePage : ContentPage
+{
+ public HomePage()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+
+ StartFloatingAnimation(BannerLogo1, 12, 8, TimeSpan.FromSeconds(12));
+ StartFloatingAnimation(BannerLogo2, -14, 8, TimeSpan.FromSeconds(10));
+ StartFloatingAnimation(BannerLogo3, -12, -12, TimeSpan.FromSeconds(14));
+ StartFloatingAnimation(BannerLogo4, 12, -8, TimeSpan.FromSeconds(11));
+ }
+
+ private static void StartFloatingAnimation(Control target, double dx, double dy, TimeSpan duration)
+ {
+ var transform = new TranslateTransform();
+ target.RenderTransform = transform;
+
+ var animation = new Animation
+ {
+ Duration = duration,
+ IterationCount = IterationCount.Infinite,
+ Children =
+ {
+ new KeyFrame
+ {
+ Cue = new Cue(0d),
+ Setters =
+ {
+ new Setter(TranslateTransform.XProperty, 0d),
+ new Setter(TranslateTransform.YProperty, 0d),
+ }
+ },
+ new KeyFrame
+ {
+ Cue = new Cue(0.5d),
+ Setters =
+ {
+ new Setter(TranslateTransform.XProperty, dx),
+ new Setter(TranslateTransform.YProperty, dy),
+ }
+ },
+ new KeyFrame
+ {
+ Cue = new Cue(1d),
+ Setters =
+ {
+ new Setter(TranslateTransform.XProperty, 0d),
+ new Setter(TranslateTransform.YProperty, 0d),
+ }
+ },
+ }
+ };
+
+ _ = animation.RunAsync(target);
+ }
+
+ private void UniformGrid_OnSizeChanged(object? sender, SizeChangedEventArgs e)
+ {
+ if (sender is not UniformGrid grid)
+ return;
+
+ const int minItemWidth = 248;
+ grid.Columns = Math.Max(
+ 1,
+ (int)((e.NewSize.Width + grid.ColumnSpacing) / (minItemWidth + grid.ColumnSpacing)));
+ }
+}
diff --git a/samples/ControlCatalog/Pages/NavigationPage/RetroGamingProfileView.xaml b/samples/ControlCatalog/Pages/NavigationPage/RetroGamingProfileView.xaml
index 17d7ff2d5a..da2215ef65 100644
--- a/samples/ControlCatalog/Pages/NavigationPage/RetroGamingProfileView.xaml
+++ b/samples/ControlCatalog/Pages/NavigationPage/RetroGamingProfileView.xaml
@@ -7,7 +7,6 @@
diff --git a/samples/ControlCatalog/Pages/PlatformSettingsPage.xaml b/samples/ControlCatalog/Pages/PlatformSettingsPage.xaml
new file mode 100644
index 0000000000..a6213558cb
--- /dev/null
+++ b/samples/ControlCatalog/Pages/PlatformSettingsPage.xaml
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/PlatformSettingsPage.xaml.cs b/samples/ControlCatalog/Pages/PlatformSettingsPage.xaml.cs
new file mode 100644
index 0000000000..8f3e6f4b48
--- /dev/null
+++ b/samples/ControlCatalog/Pages/PlatformSettingsPage.xaml.cs
@@ -0,0 +1,30 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.VisualTree;
+using ControlCatalog.ViewModels;
+
+namespace ControlCatalog.Pages
+{
+ public partial class PlatformSettingsPage : ContentPage
+ {
+ private readonly PlatformSettingsViewModel _viewModel = new();
+
+ public PlatformSettingsPage()
+ {
+ InitializeComponent();
+ DataContext = _viewModel;
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+ _viewModel.Subscribe(this.GetPlatformSettings() ?? Application.Current?.PlatformSettings);
+ }
+
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ _viewModel.Unsubscribe();
+ base.OnDetachedFromVisualTree(e);
+ }
+ }
+}
diff --git a/samples/ControlCatalog/Pages/RefreshContainerPage.axaml b/samples/ControlCatalog/Pages/RefreshContainerPage.axaml
index a905e4efdf..5e25d927ba 100644
--- a/samples/ControlCatalog/Pages/RefreshContainerPage.axaml
+++ b/samples/ControlCatalog/Pages/RefreshContainerPage.axaml
@@ -27,6 +27,7 @@
+
{
- var success = TopLevel.GetTopLevel(this)!.Screens is { } screens ?
- await screens.RequestScreenDetails() :
- false;
+ var success = TopLevel.GetTopLevel(this)!.Screens is { } screens && await screens.RequestScreenDetails();
button.Content = "Request ScreenDetails: " + (success ? "Granted" : "Denied");
};
- Content = button;
+
+ _presenter = new ScreensPagePresenter();
+
+ Content = new DockPanel
+ {
+ Children = { button, _presenter },
+ VerticalSpacing = 10,
+ Margin = new Thickness(10)
+ };
}
protected override bool BypassFlowDirectionPolicies => true;
@@ -44,131 +42,140 @@ namespace ControlCatalog.Pages
var topLevel = TopLevel.GetTopLevel(this);
if (topLevel is Window w)
{
- w.PositionChanged += (_, _) => InvalidateVisual();
+ w.PositionChanged += (_, _) => _presenter.InvalidateVisual();
}
if (topLevel?.Screens is { } screens)
{
screens.Changed += (_, _) =>
{
- Console.WriteLine("Screens Changed");
- InvalidateVisual();
+ _presenter.InvalidateVisual();
};
}
}
- public override void Render(DrawingContext context)
+ private class ScreensPagePresenter : Control
{
- base.Render(context);
- double beginOffset = (Content as Visual)?.Bounds.Height + 10 ?? 0;
-
- var topLevel = TopLevel.GetTopLevel(this)!;
- if (topLevel.Screens is not { } screens)
+ private IBrush _primaryBrush = SolidColorBrush.Parse("#FF0078D7");
+ private IBrush _defaultBrush = Brushes.LightGray;
+ private IPen _activePen = new Pen(Brushes.Black);
+ private IPen _defaultPen = new Pen(Brushes.DarkGray);
+
+ private double _leftMost;
+ private double _topMost;
+ public override void Render(DrawingContext context)
{
- var formattedText = CreateFormattedText("Current platform doesn't support Screens API.");
- context.DrawText(formattedText, new Point(15, 15 + beginOffset));
- return;
- }
+ base.Render(context);
- var activeScreen = screens.ScreenFromTopLevel(topLevel);
- double maxBottom = 0;
+ var topLevel = TopLevel.GetTopLevel(this)!;
+ if (topLevel.Screens is not { } screens)
+ {
+ var formattedText = CreateFormattedText("Current platform doesn't support Screens API.");
+ context.DrawText(formattedText, new Point(15, 15));
+ return;
+ }
- for (int i = 0; i
- public class FluidNavBar : Control, Avalonia.Rendering.ICustomHitTest
+ public partial class FluidNavBar : Control, Avalonia.Rendering.ICustomHitTest
{
internal const double NominalHeight = 56.0;
internal const double CircleRadius = 25.0;
@@ -34,26 +34,6 @@ namespace ControlCatalog.Pages
internal const double FloatUpDuration = 1.666; // s — circle rising
internal const double FloatDownDuration = 0.833; // s — circle falling
- public static readonly StyledProperty> ItemsProperty =
- AvaloniaProperty.Register>(
- nameof(Items), new List());
-
- public static readonly StyledProperty SelectedIndexProperty =
- AvaloniaProperty.Register(nameof(SelectedIndex), 0);
-
- public static readonly StyledProperty BarColorProperty =
- AvaloniaProperty.Register(nameof(BarColor), Colors.White);
-
- public static readonly StyledProperty ButtonColorProperty =
- AvaloniaProperty.Register(nameof(ButtonColor), Colors.White);
-
- public static readonly StyledProperty ActiveIconColorProperty =
- AvaloniaProperty.Register(nameof(ActiveIconColor), Colors.Black);
-
- public static readonly StyledProperty InactiveIconColorProperty =
- AvaloniaProperty.Register(
- nameof(InactiveIconColor), Color.FromArgb(140, 120, 120, 120));
-
private double _xCurrent = -1; // -1 = not yet initialised
private double _lastWidth = -1; // tracks width changes for resize correction
private double _xStart, _xTarget, _xAnimStartSec;
@@ -74,44 +54,35 @@ namespace ControlCatalog.Pages
private readonly Stopwatch _clock = Stopwatch.StartNew();
private bool _animating;
- public IList Items
- {
- get => GetValue(ItemsProperty);
- set => SetValue(ItemsProperty, value);
- }
+ [GeneratedStyledProperty]
+ public partial IReadOnlyList Items { get; set; }
- public int SelectedIndex
- {
- get => GetValue(SelectedIndexProperty);
- set => SetValue(SelectedIndexProperty, value);
- }
+ [GeneratedStyledProperty]
+ public partial int SelectedIndex { get; set; }
- public Color BarColor
- {
- get => GetValue(BarColorProperty);
- set => SetValue(BarColorProperty, value);
- }
+ [GeneratedStyledProperty]
+ public partial Color BarColor { get; set; }
- public Color ButtonColor
- {
- get => GetValue(ButtonColorProperty);
- set => SetValue(ButtonColorProperty, value);
- }
+ [GeneratedStyledProperty]
+ public partial Color ButtonColor { get; set; }
- public Color ActiveIconColor
- {
- get => GetValue(ActiveIconColorProperty);
- set => SetValue(ActiveIconColorProperty, value);
- }
+ [GeneratedStyledProperty]
+ public partial Color ActiveIconColor { get; set; }
- public Color InactiveIconColor
- {
- get => GetValue(InactiveIconColorProperty);
- set => SetValue(InactiveIconColorProperty, value);
- }
+ [GeneratedStyledProperty]
+ public partial Color InactiveIconColor { get; set; }
public event EventHandler? SelectionChanged;
+ static FluidNavBar()
+ {
+ ItemsProperty.OverrideDefaultValue([]);
+ BarColorProperty.OverrideDefaultValue(Colors.White);
+ ButtonColorProperty.OverrideDefaultValue(Colors.White);
+ ActiveIconColorProperty.OverrideDefaultValue(Colors.Black);
+ InactiveIconColorProperty.OverrideDefaultValue(Color.FromArgb(140, 120, 120, 120));
+ }
+
public FluidNavBar()
{
ClipToBounds = false;
@@ -604,7 +575,7 @@ namespace ControlCatalog.Pages
while (measure.NextContour());
}
- private static float Lerp(float a, float b, float t) => a + (b - a) * t;
+ private static float Lerp(float a, float b, float t) => float.Lerp(a, b, t);
private static double LinearPoint(double x, double pIn, double pOut)
{
diff --git a/samples/ControlCatalog/Pages/Transitions/CardStackPageTransition.cs b/samples/ControlCatalog/Pages/Transitions/CardStackPageTransition.cs
index 89ae1e5e8a..c036f0a5b3 100644
--- a/samples/ControlCatalog/Pages/Transitions/CardStackPageTransition.cs
+++ b/samples/ControlCatalog/Pages/Transitions/CardStackPageTransition.cs
@@ -424,10 +424,8 @@ public class CardStackPageTransition : PageSlide
return sign * FarPeekAngle;
}
- private static double Lerp(double from, double to, double t)
- {
- return from + ((to - from) * Math.Clamp(t, 0.0, 1.0));
- }
+ private static double Lerp(double from, double to, double t) =>
+ double.Lerp(from, to, Math.Clamp(t, 0.0, 1.0));
private static int GetViewportZIndex(double offsetFromCenter, Visual visual, Visual? from, Visual? to)
{
diff --git a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
index 5114dd16e9..f304f78898 100644
--- a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
+++ b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
@@ -9,28 +9,58 @@
x:DataType="viewModels:MainWindowViewModel"
x:CompileBindings="True"
DataContext="{Binding $parent[Window].DataContext}">
-
+
-
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -45,7 +75,7 @@
-
-
+
+
-
+
diff --git a/samples/ControlCatalog/ScrollPage.xaml b/samples/ControlCatalog/ScrollPage.xaml
index 6d5ecb815e..8c6157018f 100644
--- a/samples/ControlCatalog/ScrollPage.xaml
+++ b/samples/ControlCatalog/ScrollPage.xaml
@@ -15,7 +15,7 @@
HorizontalContentAlignment="Stretch"
IsVisible="False" />
-
new StandardCursorModel(x))
.ToList();
- var s = AssetLoader.Open(new Uri("avares://ControlCatalog/Assets/avalonia-32.png"));
+ var s = AssetLoader.Open(new Uri("avares://ControlCatalog/Assets/icon-32.png"));
var bitmap = new Bitmap(s);
CustomCursor = new Cursor(bitmap, new PixelPoint(16, 16));
}
diff --git a/samples/ControlCatalog/ViewModels/FlexItemViewModel.cs b/samples/ControlCatalog/ViewModels/FlexItemViewModel.cs
new file mode 100644
index 0000000000..9ffade90a0
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/FlexItemViewModel.cs
@@ -0,0 +1,118 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Layout;
+using Avalonia.Media;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels
+{
+ public sealed class FlexItemViewModel : ViewModelBase
+ {
+ internal const FlexAlignItems AlignSelfAuto = (FlexAlignItems)(-1);
+
+ private FlexAlignItems _alignSelf;
+
+ private bool _isSelected;
+ private bool _isVisible = true;
+
+ private FlexAlignItems _alignSelfItem = AlignSelfAuto;
+ private int _order;
+ private double _shrink = 1.0;
+ private double _grow;
+ private double _basisValue = 100.0;
+ private FlexBasisKind _basisKind;
+ private HorizontalAlignment _horizontalAlignment;
+ private VerticalAlignment _verticalAlignment;
+
+ public FlexItemViewModel(int value)
+ {
+ Value = value;
+
+ _alignSelf = AlignSelfItem == AlignSelfAuto ? default(FlexAlignItems) : AlignSelfItem;
+
+ var color = Random.Shared.Next();
+
+ Color = new SolidColorBrush((uint)color);
+ }
+
+ public int Value { get; }
+
+ public Brush Color { get; }
+
+ public bool IsSelected
+ {
+ get => _isSelected;
+ set => this.RaiseAndSetIfChanged(ref _isSelected, value);
+ }
+
+ public bool IsVisible
+ {
+ get => _isVisible;
+ set => this.RaiseAndSetIfChanged(ref _isVisible, value);
+ }
+
+ public FlexAlignItems AlignSelfItem
+ {
+ get => _alignSelfItem;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _alignSelfItem, value);
+ this.RaisePropertyChanged(nameof(AlignSelf));
+ }
+ }
+
+ public FlexAlignItems? AlignSelf => _alignSelf;
+
+ public int Order
+ {
+ get => _order;
+ set => this.RaiseAndSetIfChanged(ref _order, value);
+ }
+
+ public double Shrink
+ {
+ get => _shrink;
+ set => this.RaiseAndSetIfChanged(ref _shrink, value);
+ }
+
+ public double Grow
+ {
+ get => _grow;
+ set => this.RaiseAndSetIfChanged(ref _grow, value);
+ }
+
+ public double BasisValue
+ {
+ get => _basisValue;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _basisValue, value);
+ this.RaisePropertyChanged(nameof(Basis));
+ }
+ }
+
+ public FlexBasisKind BasisKind
+ {
+ get => _basisKind;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _basisKind, value);
+ this.RaisePropertyChanged(nameof(Basis));
+ }
+ }
+
+ public FlexBasis Basis => new(_basisValue, _basisKind);
+
+ public HorizontalAlignment HorizontalAlignment
+ {
+ get => _horizontalAlignment;
+ set => this.RaiseAndSetIfChanged(ref _horizontalAlignment, value);
+ }
+
+ public VerticalAlignment VerticalAlignment
+ {
+ get => _verticalAlignment;
+ set => this.RaiseAndSetIfChanged(ref _verticalAlignment, value);
+ }
+ }
+}
diff --git a/samples/ControlCatalog/ViewModels/FlexViewModel.cs b/samples/ControlCatalog/ViewModels/FlexViewModel.cs
new file mode 100644
index 0000000000..abc7143659
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/FlexViewModel.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows.Input;
+using Avalonia.Controls;
+using Avalonia.Layout;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels
+{
+ public sealed class FlexViewModel : ViewModelBase
+ {
+ private readonly ObservableCollection _numbers;
+
+ private FlexDirection _direction = FlexDirection.Row;
+ private FlexJustifyContent _justifyContent = FlexJustifyContent.FlexStart;
+ private FlexAlignItems _alignItems = FlexAlignItems.FlexStart;
+ private FlexAlignContent _alignContent = FlexAlignContent.FlexStart;
+ private FlexWrap _wrap = FlexWrap.Wrap;
+
+ private int _columnSpacing = 64;
+ private int _rowSpacing = 32;
+
+ private int _currentNumber = 41;
+
+ private FlexItemViewModel? _selectedItem;
+
+ public FlexViewModel()
+ {
+ _numbers = new ObservableCollection(Enumerable.Range(1, 40).Select(x => new FlexItemViewModel(x)));
+
+ Numbers = new ReadOnlyObservableCollection(_numbers);
+
+ AddItemCommand = MiniCommand.Create(AddItem);
+ RemoveItemCommand = MiniCommand.Create(RemoveItem);
+ }
+
+ public IEnumerable DirectionValues { get; } = Enum.GetValues();
+
+ public IEnumerable JustifyContentValues { get; } = Enum.GetValues();
+
+ public IEnumerable AlignItemsValues { get; } = Enum.GetValues();
+
+ public IEnumerable AlignContentValues { get; } = Enum.GetValues();
+
+ public IEnumerable WrapValues { get; } = Enum.GetValues();
+
+ public IEnumerable FlexBasisKindValues { get; } = Enum.GetValues();
+
+ public IEnumerable HorizontalAlignmentValues { get; } = Enum.GetValues();
+
+ public IEnumerable VerticalAlignmentValues { get; } = Enum.GetValues();
+
+ public IEnumerable AlignSelfValues { get; } = Enum.GetValues().Cast().Prepend(FlexItemViewModel.AlignSelfAuto);
+
+ public FlexDirection Direction
+ {
+ get => _direction;
+ set => this.RaiseAndSetIfChanged(ref _direction, value);
+ }
+
+ public FlexJustifyContent JustifyContent
+ {
+ get => _justifyContent;
+ set => this.RaiseAndSetIfChanged(ref _justifyContent, value);
+ }
+
+ public FlexAlignItems AlignItems
+ {
+ get => _alignItems;
+ set => this.RaiseAndSetIfChanged(ref _alignItems, value);
+ }
+
+ public FlexAlignContent AlignContent
+ {
+ get => _alignContent;
+ set => this.RaiseAndSetIfChanged(ref _alignContent, value);
+ }
+
+ public FlexWrap Wrap
+ {
+ get => _wrap;
+ set => this.RaiseAndSetIfChanged(ref _wrap, value);
+ }
+
+ public int ColumnSpacing
+ {
+ get => _columnSpacing;
+ set => this.RaiseAndSetIfChanged(ref _columnSpacing, value);
+ }
+
+ public int RowSpacing
+ {
+ get => _rowSpacing;
+ set => this.RaiseAndSetIfChanged(ref _rowSpacing, value);
+ }
+
+ public ReadOnlyObservableCollection Numbers { get; }
+
+ public FlexItemViewModel? SelectedItem
+ {
+ get => _selectedItem;
+ set => this.RaiseAndSetIfChanged(ref _selectedItem, value);
+ }
+
+ public ICommand AddItemCommand { get; }
+
+ public ICommand RemoveItemCommand { get; }
+
+ private void AddItem() => _numbers.Add(new FlexItemViewModel(_currentNumber++));
+
+ private void RemoveItem()
+ {
+ if (SelectedItem is null)
+ {
+ return;
+ }
+
+ _numbers.Remove(SelectedItem);
+
+ SelectedItem.IsSelected = false;
+ SelectedItem = null;
+ }
+ }
+}
diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
index 5d14cca1ee..0c4edb29a5 100644
--- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
@@ -1,26 +1,25 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Controls.Chrome;
using Avalonia.Dialogs;
using System;
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Runtime.CompilerServices;
using Avalonia;
+using Avalonia.Collections;
+using ControlCatalog.Models;
using MiniMvvm;
namespace ControlCatalog.ViewModels
{
partial class MainWindowViewModel : ViewModelBase
{
- private WindowState _windowState;
- private WindowState[] _windowStates = Array.Empty();
- private bool _extendClientAreaEnabled;
- private double _titleBarHeight;
- private bool _isSystemBarVisible;
- private bool _displayEdgeToEdge;
- private Thickness _safeAreaPadding;
- private bool _canResize;
- private bool _canMinimize;
- private bool _canMaximize;
- private int _selectedDecorationIndex;
+ private readonly AvaloniaList _filteredPages = [];
+
+ private bool _ignoreListChange;
+ private PageItem? _currentItem;
public MainWindowViewModel()
{
@@ -37,6 +36,7 @@ namespace ControlCatalog.ViewModels
{
(App.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Shutdown();
});
+ NavigateToPageCommand = MiniCommand.Create(NavigateToPage);
WindowState = WindowState.Normal;
@@ -54,79 +54,177 @@ namespace ControlCatalog.ViewModels
CanMaximize = true;
Filter();
- }
-
+ }
+
+ public IReadOnlyList HomeSections =>
+ // Home page doesn't have a section title and should be excluded from this list
+ field ??= _pageSections.Where(s => !string.IsNullOrEmpty(s.Title)).ToArray();
+
+ public IReadOnlyList Pages => _filteredPages;
+
+ public INavigation? Navigator { get; internal set; }
+
public bool ExtendClientAreaEnabled
{
- get { return _extendClientAreaEnabled; }
- set { RaiseAndSetIfChanged(ref _extendClientAreaEnabled, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public double TitleBarHeight
{
- get { return _titleBarHeight; }
- set { RaiseAndSetIfChanged(ref _titleBarHeight, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public WindowState WindowState
{
- get { return _windowState; }
- set { RaiseAndSetIfChanged(ref _windowState, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public WindowState[] WindowStates
{
- get { return _windowStates; }
- set { RaiseAndSetIfChanged(ref _windowStates, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public bool IsSystemBarVisible
{
- get { return _isSystemBarVisible; }
- set { RaiseAndSetIfChanged(ref _isSystemBarVisible, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public bool DisplayEdgeToEdge
{
- get { return _displayEdgeToEdge; }
- set { RaiseAndSetIfChanged(ref _displayEdgeToEdge, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
-
+
public Thickness SafeAreaPadding
{
- get { return _safeAreaPadding; }
- set { RaiseAndSetIfChanged(ref _safeAreaPadding, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public bool CanResize
{
- get { return _canResize; }
- set { RaiseAndSetIfChanged(ref _canResize, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public bool CanMinimize
{
- get { return _canMinimize; }
- set { RaiseAndSetIfChanged(ref _canMinimize, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public bool CanMaximize
{
- get { return _canMaximize; }
- set { RaiseAndSetIfChanged(ref _canMaximize, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public int SelectedDecorationIndex
{
- get { return _selectedDecorationIndex; }
- set { RaiseAndSetIfChanged(ref _selectedDecorationIndex, value); }
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
+ }
+
+ public TitleBarDecorations TitleBarDecorations
+ {
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
+ } = TitleBarDecorations.All;
+
+ public bool ShowTitle
+ {
+ get => HasTitleBarDecoration(TitleBarDecorations.Title);
+ set => SetTitleBarDecoration(TitleBarDecorations.Title, value);
+ }
+
+ public bool ShowFullScreenButton
+ {
+ get => HasTitleBarDecoration(TitleBarDecorations.FullScreenButton);
+ set => SetTitleBarDecoration(TitleBarDecorations.FullScreenButton, value);
+ }
+
+ public bool ShowMinimizeButton
+ {
+ get => HasTitleBarDecoration(TitleBarDecorations.MinimizeButton);
+ set => SetTitleBarDecoration(TitleBarDecorations.MinimizeButton, value);
+ }
+
+ public bool ShowMaximizeButton
+ {
+ get => HasTitleBarDecoration(TitleBarDecorations.MaximizeButton);
+ set => SetTitleBarDecoration(TitleBarDecorations.MaximizeButton, value);
+ }
+
+ public bool ShowCloseButton
+ {
+ get => HasTitleBarDecoration(TitleBarDecorations.CloseButton);
+ set => SetTitleBarDecoration(TitleBarDecorations.CloseButton, value);
+ }
+
+ public int SelectedPageIndex
+ {
+ get;
+ set
+ {
+ RaiseAndSetIfChanged(ref field, value);
+
+ if (!_ignoreListChange)
+ {
+ NavigateTo(field);
+
+ if (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay)
+ IsDrawerOpened = false;
+ }
+ }
+ }
+
+ public bool IsDrawerOpened
+ {
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
+ } = true;
+
+ public SplitViewDisplayMode DisplayMode
+ {
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
+ }
+
+ public string? Query
+ {
+ get;
+ set
+ {
+ RaiseAndSetIfChanged(ref field, value);
+
+ Filter(value);
+ }
+ } = "";
+
+ private bool HasTitleBarDecoration(TitleBarDecorations decoration)
+ => (TitleBarDecorations & decoration) != 0;
+
+ private void SetTitleBarDecoration(TitleBarDecorations decoration, bool value, [CallerMemberName] string? propertyName = null)
+ {
+ var newDecorations = value ? TitleBarDecorations | decoration : TitleBarDecorations & ~decoration;
+ if (newDecorations == TitleBarDecorations)
+ return;
+
+ TitleBarDecorations = newDecorations;
+ RaisePropertyChanged(propertyName);
+ RaisePropertyChanged(nameof(TitleBarDecorations));
}
public MiniCommand AboutCommand { get; }
public MiniCommand ExitCommand { get; }
- private DateTime? _validatedDateExample;
+ public MiniCommand NavigateToPageCommand { get; }
///
/// A required DateTime which should demonstrate validation for the DateTimePicker
@@ -134,8 +232,8 @@ namespace ControlCatalog.ViewModels
[Required]
public DateTime? ValidatedDateExample
{
- get => _validatedDateExample;
- set => RaiseAndSetIfChanged(ref _validatedDateExample, value);
+ get;
+ set => RaiseAndSetIfChanged(ref field, value);
}
public Win32Properties.WindowCornerPreference[] Win32WindowCornerPreferences { get; } =
@@ -144,7 +242,84 @@ namespace ControlCatalog.ViewModels
public Win32Properties.WindowCornerPreference Win32WindowCornerPreference
{
get;
- set { RaiseAndSetIfChanged(ref field, value); }
+ set => RaiseAndSetIfChanged(ref field, value);
+ }
+
+ public void NavigateToPage(PageItem item)
+ {
+ // Clear any active search so the target is present in the filtered list.
+ if (!string.IsNullOrEmpty(Query))
+ Query = "";
+
+ var index = _filteredPages.IndexOf(item);
+ if (index >= 0)
+ SelectedPageIndex = index;
+ }
+
+ public void Filter(string? query = "")
+ {
+ try
+ {
+ _ignoreListChange = true;
+ _filteredPages.Clear();
+
+ // Left panel items are sorted alphabetically
+ var allPages = _pageSections
+ .SelectMany(cat => cat.Items)
+ .OrderBy(p => p.Header == "Home" ? 0 : 1)
+ .ThenBy(p => p.Header);
+
+ if (string.IsNullOrWhiteSpace(query))
+ {
+ _filteredPages.AddRange(allPages);
+ }
+ else
+ {
+ var querySearchKey = PageItem.CreateSearchKey(query);
+
+ if (querySearchKey.Length == 0)
+ {
+ _filteredPages.AddRange(allPages);
+ }
+ else
+ {
+ foreach (var item in allPages)
+ {
+ if (item.MatchesSearch(querySearchKey))
+ {
+ _filteredPages.Add(item);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ _ignoreListChange = false;
+ if (_currentItem != null)
+ {
+ var newIndex = _filteredPages.IndexOf(_currentItem);
+ if (newIndex != -1)
+ {
+ SelectedPageIndex = newIndex;
+ }
+ }
+ }
+ }
+
+ private async void NavigateTo(int pageIndex)
+ {
+ if (pageIndex < 0 || pageIndex >= Pages.Count || Navigator is null)
+ return;
+
+ var item = Pages[pageIndex];
+ var page = item.CreatePage();
+
+ if (page.GetType() != Navigator.NavigationStack.LastOrDefault()?.GetType())
+ {
+ _currentItem = item;
+ await Navigator.ReplaceAsync(page);
+ }
}
}
}
diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs
index 250b1358b5..907cd80c34 100644
--- a/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs
+++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs
@@ -1,249 +1,141 @@
-using Avalonia.Controls;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Dialogs;
using System;
-using System.ComponentModel.DataAnnotations;
-using Avalonia;
-using MiniMvvm;
-using Avalonia.Collections;
-using ControlCatalog.Pages;
-using System.Globalization;
-using System.Text;
-using System.Threading.Tasks;
using System.Collections.Generic;
-using System.Linq;
+using Avalonia.Controls;
+using ControlCatalog.Pages;
+using Avalonia.Media;
+using ControlCatalog.Models;
-namespace ControlCatalog.ViewModels
-{
- partial class MainWindowViewModel
- {
- private int _selectedPageIndex;
- private bool _isDrawerOpened = true;
- private bool _ignoreListChange = false;
- private string? _query = "";
- private PageItem? _currentItem;
- private SplitViewDisplayMode _displayMode;
+namespace ControlCatalog.ViewModels;
- private List _items = new()
+partial class MainWindowViewModel
+{
+ private readonly HomeSection[] _pageSections =
+ [
+ Section("", s =>
{
- new PageItem("Composition", () => new CompositionPage(), Icons.Layers),
- new PageItem("Accelerator", () => new AcceleratorPage(), Icons.Keyboard),
- new PageItem("Acrylic", () => new AcrylicPage(), Icons.Blur),
- new PageItem("AdornerLayer", () => new AdornerLayerPage(), Icons.Sparkle),
- new PageItem("AutoCompleteBox",() => new AutoCompleteBoxPage(), Icons.TextInput),
- new PageItem("Border",() => new BorderPage(), Icons.Border),
- new PageItem("BitmapCache",() => new BitmapCachePage(), Icons.Lightning),
- new PageItem("Buttons",() => new ButtonsPage(), Icons.CursorClick),
- new PageItem("ButtonSpinner",() => new ButtonSpinnerPage(), Icons.Spinner),
- new PageItem("Calendar",() => new CalendarPage(), Icons.Calendar),
- new PageItem("Canvas",() => new CanvasPage(), Icons.Canvas),
- new PageItem("CommandBar",() => new CommandBarPage(), Icons.Terminal),
- new PageItem("Carousel",() => new Pages.CarouselPage(), Icons.Slides),
- new PageItem("CarouselPage",() => new CarouselDemoPage(), Icons.Slides),
- new PageItem("CheckBox",() => new CheckBoxPage(), Icons.Checkbox),
- new PageItem("Clipboard",() => new ClipboardPage(), Icons.Clipboard),
- new PageItem("ColorPicker",() => new ColorPickerPage(), Icons.Palette),
- new PageItem("ComboBox",() => new ComboBoxPage(), Icons.Dropdown),
- new PageItem("Container Queries",() => new ContainerQueryPage(), Icons.Container),
- new PageItem("ContentPage",() => new ContentDemoPage(), Icons.Document),
- new PageItem("ContextFlyout",() => new ContextFlyoutPage(), Icons.Menu),
- new PageItem("ContextMenu",() => new ContextMenuPage(), Icons.Menu),
- new PageItem("Cursor",() => new CursorPage(), Icons.Cursor),
- new PageItem("Custom Drawing",() => new CustomDrawing(), Icons.Brush),
- new PageItem("Data Validation",() => new DataValidationPage(), Icons.Shield),
- new PageItem("Date/Time Picker",() => new DateTimePickerPage(), Icons.Clock),
- new PageItem("CalendarDatePicker",() => new CalendarDatePickerPage(), Icons.Calendar),
- new PageItem("Dialogs",() => new DialogsPage(), Icons.Dialog),
- new PageItem("Drag+Drop",() => new DragAndDropPage(), Icons.DragDrop),
- new PageItem("DrawerPage",() => new DrawerDemoPage(), Icons.Drawer),
- new PageItem("Expander",() => new ExpanderPage(), Icons.Expand),
- new PageItem("Flyouts",() => new FlyoutsPage(), Icons.Flyout),
- new PageItem("Focus",() => new FocusPage(), Icons.Target),
- new PageItem("Gestures",() => new GesturePage(), Icons.Gesture),
- new PageItem("Image",() => new ImagePage(), Icons.Image),
- new PageItem("Label",() => new LabelsPage(), Icons.Tag),
- new PageItem("LayoutTransformControl",() => new LayoutTransformControlPage(), Icons.Transform),
- new PageItem("ListBox",() => new ListBoxPage(), Icons.List),
- new PageItem("Menu",() => new MenuPage(), Icons.Menu),
- new PageItem("NavigationPage",() => new NavigationDemoPage(), Icons.Navigation),
- new PageItem("Notifications",() => new NotificationsPage(), Icons.Bell),
- new PageItem("NumericUpDown",() => new NumericUpDownPage(), Icons.Number),
- new PageItem("OpenGL",() => new OpenGlPage(), Icons.Cube3D),
- new PageItem("OpenGL Lease",() => new OpenGlLeasePage(), Icons.Cube3D),
- new PageItem("PipsPager",() => new PipsPagerPage(), Icons.HorizontalDots),
- new PageItem("Platform Information",() => new PlatformInfoPage(), Icons.Info),
- new PageItem("Pointers",() => new PointersPage(), Icons.Cursor),
- new PageItem("ProgressBar",() => new ProgressBarPage(), Icons.Progress),
- new PageItem("RadioButton",() => new RadioButtonPage(), Icons.Radio),
- new PageItem("RefreshContainer",() => new RefreshContainerPage(), Icons.Refresh),
- new PageItem("RelativePanel",() => new RelativePanelPage(), Icons.Layout),
- new PageItem("ScrollViewer",() => new ScrollViewerPage(), Icons.Scroll),
- new PageItem("Slider",() => new SliderPage(), Icons.Tune),
- new PageItem("SplitView",() => new SplitViewPage(), Icons.Split),
- new PageItem("TabbedPage",() => new TabbedDemoPage(), Icons.Tab),
- new PageItem("TabControl",() => new TabControlPage(), Icons.Tab),
- new PageItem("TabStrip",() => new TabStripPage(), Icons.Tab),
- new PageItem("TableView",() => new TableViewPage(), Icons.Grid),
- new PageItem("TextBox",() => new TextBoxPage(), Icons.TextInput),
- new PageItem("TextBlock",() => new TextBlockPage(), Icons.TextInput),
- new PageItem("Theme Variants",() => new ThemePage(), Icons.Theme),
- new PageItem("ToggleSwitch",() => new ToggleSwitchPage(), Icons.Toggle),
- new PageItem("ToolTip",() => new ToolTipPage(), Icons.Tooltip),
- new PageItem("TransitioningContentControl",() => new TransitioningContentControlPage(), Icons.Transition),
- new PageItem("TreeView",() => new TreeViewPage(), Icons.Tree),
- new PageItem("Viewbox",() => new ViewboxPage(), Icons.Viewbox),
- new PageItem("WrapPanel",() => new WrapPanelPage(), Icons.Layout),
- new PageItem("Native Embed",() => new NativeEmbedPage(), Icons.Puzzle),
- new PageItem("Window Customizations",() => new WindowCustomizationsPage(), Icons.Window),
- new PageItem("HeaderedContentControl",() => new HeaderedContentPage(), Icons.Header),
- new PageItem("Screens",() => new ScreenPage(), Icons.Monitor),
- };
-
- public AvaloniaList Pages { get; } = new AvaloniaList();
-
- public void Filter(string? query = "")
+ s.Add("Home", Icons.Home, "Overview of everything in the catalog");
+ }),
+ Section("Basic Input", s =>
{
- try
- {
- _ignoreListChange = true;
- Pages.Clear();
-
- if (string.IsNullOrWhiteSpace(query))
- {
- Pages.AddRange(_items);
- }
- else
- {
- var querySearchKey = PageItem.CreateSearchKey(query);
-
- if (querySearchKey.Length == 0)
- {
- Pages.AddRange(_items);
- }
- else
- {
- foreach (var item in _items)
- {
- if (item.MatchesSearch(querySearchKey))
- {
- Pages.Add(item);
- }
- }
- }
- }
- }
- finally
- {
- _ignoreListChange = false;
- if (_currentItem != null)
- {
- var newIndex = Pages.IndexOf(_currentItem);
- if (newIndex != -1)
- {
- SelectedPageIndex = newIndex;
- }
- }
- }
- }
-
- public INavigation? Navigator { get; internal set; }
-
- public int SelectedPageIndex
+ s.Add("Buttons", Icons.CursorClick, "Button, RepeatButton, ToggleButton and friends");
+ s.Add("ButtonSpinner", Icons.Spinner, "Content with increment and decrement buttons");
+ s.Add("CheckBox", Icons.Checkbox, "Two- and three-state check boxes");
+ s.Add("ColorPicker", Icons.Palette, "Pick colors from spectrum and palette views");
+ s.Add("ComboBox", Icons.Dropdown, "A drop-down list of selectable items");
+ s.Add("NumericUpDown", Icons.Number, "Numeric input with spinner buttons");
+ s.Add("RadioButton", Icons.Radio, "Mutually exclusive option groups");
+ s.Add("Slider", Icons.Tune, "Select a value from a continuous range");
+ s.Add("ToggleSwitch", Icons.Toggle, "An on/off switch with a sliding knob");
+ }),
+ Section("Text", s =>
{
- get { return _selectedPageIndex; }
- set
- {
- RaiseAndSetIfChanged(ref _selectedPageIndex, value);
-
- if (!_ignoreListChange)
- {
- NavigateTo(_selectedPageIndex);
-
- if (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay)
- IsDrawerOpened = false;
- }
- }
- }
-
- public bool IsDrawerOpened
+ s.Add("AutoCompleteBox", Icons.TextInput, "Text input with completion suggestions");
+ s.Add("Label", Icons.Tag, "Captions with access keys for other controls");
+ s.Add("TextBox", Icons.TextInput, "Single- and multi-line text editing");
+ s.Add("TextBlock", Icons.TextInput, "Styled read-only text display");
+ }),
+ Section("Collections & Data", s =>
{
- get { return _isDrawerOpened; }
- set { RaiseAndSetIfChanged(ref _isDrawerOpened, value); }
- }
-
- public SplitViewDisplayMode DisplayMode
+ s.Add("Carousel", Icons.Slides, "Cycle through a collection of items");
+ s.Add("ListBox", Icons.List, "A selectable, virtualized list of items");
+ s.Add("PipsPager", Icons.HorizontalDots, "Dot-style pager for paginated content");
+ s.Add("RefreshContainer", Icons.Refresh, "Pull-to-refresh for scrollable content");
+ s.Add("TableView", Icons.Grid, "Tabular data with resizable, sortable columns");
+ s.Add("TreeView", Icons.Tree, "Hierarchical data with expandable nodes");
+ }),
+ Section("Date & Time", s =>
{
- get { return _displayMode; }
- set { RaiseAndSetIfChanged(ref _displayMode, value); }
- }
-
- public string? Query
+ s.Add("Calendar", Icons.Calendar, "A month calendar for selecting dates");
+ s.Add("CalendarDatePicker", Icons.Calendar, "A date picker with a drop-down calendar");
+ s.Add("Date/Time Picker", Icons.Clock, "Spinner-style date and time pickers");
+ }),
+ Section("Menus & Flyouts", s =>
{
- get { return _query; }
- set
- {
- RaiseAndSetIfChanged(ref _query, value);
-
- Filter(value);
- }
- }
-
- private async void NavigateTo(int pageIndex)
+ s.Add("CommandBar", Icons.Terminal, "A toolbar of commands with an overflow menu");
+ s.Add("ContextFlyout", Icons.Menu, "Attach flyouts shown on right-click");
+ s.Add("ContextMenu", Icons.Menu, "Traditional right-click context menus");
+ s.Add("Flyouts", Icons.Flyout, "Lightweight popups anchored to controls");
+ s.Add("Menu", Icons.Menu, "Menu bars with nested menu items");
+ }),
+ Section("Navigation & Pages", s =>
{
- if (pageIndex < 0 || pageIndex >= Pages.Count || Navigator is null)
- return;
-
- var item = Pages[pageIndex];
-
- if (item != null)
- {
- var view = item.Factory();
- if (view is Page page && view.GetType() != Navigator.NavigationStack.LastOrDefault()?.GetType())
- {
- _currentItem = item;
- await Navigator.ReplaceAsync(page);
- }
- }
- }
+ s.Add("CarouselPage", Icons.Slides, "Swipeable page-based navigation");
+ s.Add("ContentPage", Icons.Document, "A page that hosts a single content view");
+ s.Add("DrawerPage", Icons.Drawer, "A page with a sliding navigation drawer");
+ s.Add("NavigationPage", Icons.Navigation, "Stack-based page navigation");
+ s.Add("SplitView", Icons.Split, "A collapsible pane beside content");
+ s.Add("TabbedPage", Icons.Tab, "Tab-based page navigation");
+ s.Add("TabControl", Icons.Tab, "Switch between tabbed content views");
+ s.Add("TabStrip", Icons.Tab, "A standalone strip of selectable tabs");
+ }),
+ Section("Layout", s =>
+ {
+ s.Add("Border", Icons.Border, "Decorate elements with borders and corner radii");
+ s.Add("Canvas", Icons.Canvas, "Position children at explicit coordinates");
+ s.Add("Container Queries", Icons.Container, "Styles that respond to container size");
+ s.Add("Expander", Icons.Expand, "A header that expands to reveal content");
+ s.Add("Flex Panel", Icons.Grid, "Flexible, CSS-style child layout");
+ s.Add("HeaderedContentControl", Icons.Header, "Content paired with a header");
+ s.Add("LayoutTransformControl", Icons.Transform, "Apply transforms that affect layout");
+ s.Add("RelativePanel", Icons.Layout, "Arrange children relative to each other");
+ s.Add("ScrollViewer", Icons.Scroll, "Scrollable viewport over large content");
+ s.Add("Viewbox", Icons.Viewbox, "Scale content to fit available space");
+ s.Add("WrapPanel", Icons.Layout, "Wrap children onto multiple lines");
+ }),
+ Section("Media & Graphics", s =>
+ {
+ s.Add("Acrylic", Icons.Blur, "Translucent acrylic window materials");
+ s.Add("BitmapCache", Icons.Lightning, "Cache visuals as bitmaps for performance");
+ s.Add("Composition", Icons.Layers, "Composition-layer animations and effects");
+ s.Add("Custom Drawing", Icons.Brush, "Render custom geometry in code");
+ s.Add("Image", Icons.Image, "Display bitmaps with different stretch modes");
+ s.Add("OpenGL", Icons.Cube3D, "Embed custom OpenGL rendering");
+ s.Add("OpenGL Lease", Icons.Cube3D, "Low-level access to the OpenGL context");
+ s.Add("TransitioningContentControl", Icons.Transition, "Animate between content changes");
+ }),
+ Section("Status & Feedback", s =>
+ {
+ s.Add("AdornerLayer", Icons.Sparkle, "Overlay visuals on top of other controls");
+ s.Add("Data Validation", Icons.Shield, "Display validation errors from bindings");
+ s.Add("Dialogs", Icons.Dialog, "File pickers and modal dialog windows");
+ s.Add("Notifications", Icons.Bell, "Toast-style in-app notifications");
+ s.Add("ProgressBar", Icons.Progress, "Determinate and indeterminate progress");
+ s.Add("ToolTip", Icons.Tooltip, "Hover hints for any control");
+ }),
+ Section("Interaction", s =>
+ {
+ s.Add("Accelerator", Icons.Keyboard, "Keyboard shortcuts that invoke commands");
+ s.Add("Clipboard", Icons.Clipboard, "Read from and write to the system clipboard");
+ s.Add("Cursor", Icons.Cursor, "Change the pointer cursor over elements");
+ s.Add("Drag+Drop", Icons.DragDrop, "Drag data within and between applications");
+ s.Add("Focus", Icons.Target, "Track and control keyboard focus");
+ s.Add("Gestures", Icons.Gesture, "Tap, scroll and pinch gesture recognition");
+ s.Add("Pointers", Icons.Cursor, "Raw pointer input and capture");
+ }),
+ Section("Window & Platform", s =>
+ {
+ s.Add("Native Embed", Icons.Puzzle, "Host native platform controls");
+ s.Add("Platform Information", Icons.Info, "Runtime platform and capability info");
+ s.Add("Platform Settings", Icons.Tune, "Platform-specific system settings");
+ s.Add("Screens", Icons.Monitor, "Enumerate displays and their bounds");
+ s.Add("Theme Variants", Icons.Theme, "Switch between light and dark variants");
+ s.Add("Window Customizations", Icons.Window, "Custom chrome, decorations and sizing");
+ })
+ ];
+
+ private static HomeSection Section(string title, Action builderCallback)
+ {
+ var builder = new HomeSectionBuilder(title);
+ builderCallback(builder);
+ return new HomeSection(title, builder.ToArray());
}
- class PageItem(string header, Func
-
- Resources\drawable\Icon.png
+
+ Resources\drawable\icon.png
diff --git a/samples/SafeAreaDemo.Desktop/SafeAreaDemo.Desktop.csproj b/samples/SafeAreaDemo.Desktop/SafeAreaDemo.Desktop.csproj
index e2fca22929..f990c9ff57 100644
--- a/samples/SafeAreaDemo.Desktop/SafeAreaDemo.Desktop.csproj
+++ b/samples/SafeAreaDemo.Desktop/SafeAreaDemo.Desktop.csproj
@@ -15,5 +15,6 @@
+
diff --git a/samples/SafeAreaDemo/Assets/avalonia-logo.ico b/samples/SafeAreaDemo/Assets/avalonia-logo.ico
deleted file mode 100644
index da8d49ff9b..0000000000
Binary files a/samples/SafeAreaDemo/Assets/avalonia-logo.ico and /dev/null differ
diff --git a/samples/SafeAreaDemo/Views/MainView.xaml b/samples/SafeAreaDemo/Views/MainView.xaml
index c62410aa83..1a33683ab6 100644
--- a/samples/SafeAreaDemo/Views/MainView.xaml
+++ b/samples/SafeAreaDemo/Views/MainView.xaml
@@ -9,64 +9,77 @@
x:Class="SafeAreaDemo.Views.MainView"
x:DataType="vm:MainViewModel"
TopLevel.AutoSafeAreaPadding="{Binding AutoSafeAreaPadding, Mode=TwoWay}">
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+ Display Edge To Edge
+ Use Safe Area
+ Automatic Paddings
+ Hide System Bars
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- Display Edge To Edge
- Use Safe Area
- Automatic Paddings
- Hide System Bars
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/samples/SafeAreaDemo/Views/MainWindow.xaml b/samples/SafeAreaDemo/Views/MainWindow.xaml
index ccd3028bb9..866c2a256d 100644
--- a/samples/SafeAreaDemo/Views/MainWindow.xaml
+++ b/samples/SafeAreaDemo/Views/MainWindow.xaml
@@ -6,7 +6,6 @@
xmlns:views="clr-namespace:SafeAreaDemo.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SafeAreaDemo.Views.MainWindow"
- Icon="/Assets/avalonia-logo.ico"
Title="SafeAreaDemo">
diff --git a/samples/SingleProjectSandbox/Platforms/Browser/wwwroot/favicon.ico b/samples/SingleProjectSandbox/Platforms/Browser/wwwroot/favicon.ico
index da8d49ff9b..b5ce607b0e 100644
Binary files a/samples/SingleProjectSandbox/Platforms/Browser/wwwroot/favicon.ico and b/samples/SingleProjectSandbox/Platforms/Browser/wwwroot/favicon.ico differ
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index befdcbcd5e..e22990d18c 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs b/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
index 2943e13a21..0bec287fed 100644
--- a/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
+++ b/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
@@ -49,6 +49,14 @@ namespace Avalonia.Android
private readonly Dictionary> _peerNodeInfoProviders;
+ ///
+ /// Virtual view IDs must be allocated from a monotonic counter rather than derived from
+ /// the size of : entries are now removed when their
+ /// owner leaves the visual tree, so the dictionary's count no longer grows monotonically
+ /// and reusing it would hand out an ID that is still in use.
+ ///
+ private int _nextPeerViewId;
+
private readonly AvaloniaView _view;
public AvaloniaAccessHelper(AvaloniaView view) : base(view)
@@ -85,16 +93,16 @@ namespace Avalonia.Android
}
else
{
- peerViewId = _peerNodeInfoProviders.Count;
+ peerViewId = _nextPeerViewId++;
_peers.Add(peerViewId, peer);
_peerIds.Add(peer, peerViewId);
nodeInfoProviders = new();
_peerNodeInfoProviders.Add(peer, nodeInfoProviders);
- peer.ChildrenChanged += (s, ev) => InvalidateVirtualView(peerViewId,
+ EventHandler childrenChanged = (s, ev) => InvalidateVirtualView(peerViewId,
AccessibilityEventCompat.ContentChangeTypeSubtree);
- peer.PropertyChanged += (s, ev) =>
+ EventHandler propertyChanged = (s, ev) =>
{
if (ev.Property == AutomationElementIdentifiers.NameProperty)
{
@@ -104,13 +112,42 @@ namespace Avalonia.Android
{
InvalidateVirtualView(peerViewId, AccessibilityEventCompat.ContentChangeTypeContentDescription);
}
- else if (ev.Property == AutomationElementIdentifiers.BoundingRectangleProperty ||
+ else if (ev.Property == AutomationElementIdentifiers.BoundingRectangleProperty ||
ev.Property == AutomationElementIdentifiers.ClassNameProperty)
{
InvalidateVirtualView(peerViewId);
}
};
+ peer.ChildrenChanged += childrenChanged;
+ peer.PropertyChanged += propertyChanged;
+
+ // Drop the registration once the peer's control leaves the visual tree, otherwise
+ // every control ever explored by accessibility is kept alive for the lifetime of
+ // the view: the peer holds a strong reference to its Owner, and these three
+ // dictionaries were never pruned. On a long-running app that rebuilds its UI (for
+ // instance digital signage swapping screens), this retains each dead visual tree in
+ // full — measured at ~2.5 MB per rebuild on a real device.
+ // The root peer (ID 0) is deliberately never unregistered: GetVirtualViewAt and
+ // GetVisibleVirtualViews index _peers[0] directly, so removing it would throw.
+ // It is a single entry owned by the view itself, and dies with the helper.
+ if (peerViewId != 0 && peer is ControlAutomationPeer controlPeer)
+ {
+ EventHandler? detachedFromVisualTree = null;
+ detachedFromVisualTree = (s, ev) =>
+ {
+ controlPeer.Owner.DetachedFromVisualTree -= detachedFromVisualTree;
+ peer.ChildrenChanged -= childrenChanged;
+ peer.PropertyChanged -= propertyChanged;
+
+ _peers.Remove(peerViewId);
+ _peerIds.Remove(peer);
+ _peerNodeInfoProviders.Remove(peer);
+ };
+
+ controlPeer.Owner.DetachedFromVisualTree += detachedFromVisualTree;
+ }
+
if (peer.GetProvider() is not null)
nodeInfoProviders.Add(new ExpandCollapseNodeInfoProvider(this, peer, peerViewId));
if (peer.GetProvider() is not null)
diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs
index a5a45be61a..96a95b8a12 100644
--- a/src/Android/Avalonia.Android/AvaloniaView.cs
+++ b/src/Android/Avalonia.Android/AvaloniaView.cs
@@ -23,7 +23,7 @@ namespace Avalonia.Android
private readonly ViewImpl _view;
private readonly ExploreByTouchHelper _accessHelper;
- private IDisposable? _timerSubscription;
+ private bool _isRendering;
private bool _surfaceCreated;
public AvaloniaView(Context context) : base(context)
@@ -106,13 +106,9 @@ namespace Avalonia.Android
if (_root == null || !_surfaceCreated)
return;
- if (isVisible && _timerSubscription == null)
+ if (isVisible && !_isRendering)
{
- if (AndroidPlatform.Timer is { } timer)
- {
- _timerSubscription = timer.SubscribeView(this);
- }
-
+ _isRendering = true;
_root.StartRendering();
if (_view.TryGetFeature(out var insetsManager) == true)
@@ -120,11 +116,10 @@ namespace Avalonia.Android
(insetsManager as AndroidInsetsManager)?.ApplyStatusBarState();
}
}
- else if (!isVisible && _timerSubscription != null)
+ else if (!isVisible && _isRendering)
{
+ _isRendering = false;
_root.StopRendering();
- _timerSubscription?.Dispose();
- _timerSubscription = null;
}
}
@@ -137,11 +132,8 @@ namespace Avalonia.Android
private void SendConfigurationChanged(Configuration? newConfig)
{
_view.InsetsManager?.SetDefaultSystemLightMode(!(newConfig?.UiMode.HasFlag(UiMode.NightYes) ?? false));
- if (Context is { } context && newConfig is { } config)
+ if (Context is not null && newConfig is not null)
{
- var settings =
- AvaloniaLocator.Current.GetRequiredService() as AndroidPlatformSettings;
- settings?.OnViewConfigurationChanged(context, config);
((AndroidScreens)_view.TryGetFeature()!).OnChanged();
}
}
diff --git a/src/Android/Avalonia.Android/ChoreographerTimer.cs b/src/Android/Avalonia.Android/ChoreographerTimer.cs
index 9bc8e78a52..d31a0aa915 100644
--- a/src/Android/Avalonia.Android/ChoreographerTimer.cs
+++ b/src/Android/Avalonia.Android/ChoreographerTimer.cs
@@ -1,9 +1,7 @@
using System;
-using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
-using Avalonia.Reactive;
using Avalonia.Rendering;
using static Avalonia.Android.Platform.SkiaPlatform.AndroidFramebuffer;
@@ -17,7 +15,6 @@ namespace Avalonia.Android
private readonly TaskCompletionSource _choreographer = new();
private readonly AutoResetEvent _event = new(false);
private readonly GCHandle _timerHandle;
- private readonly HashSet _views = new();
private Action? _tick;
private bool _pendingCallback;
private long _lastTime;
@@ -49,23 +46,6 @@ namespace Avalonia.Android
}
}
- internal IDisposable SubscribeView(AvaloniaView view)
- {
- lock (_lock)
- {
- _views.Add(view);
- PostFrameCallbackIfNeeded();
- }
-
- return Disposable.Create(
- () =>
- {
- lock (_lock)
- _views.Remove(view);
- }
- );
- }
-
private void Loop()
{
Looper.Prepare();
@@ -94,7 +74,7 @@ namespace Avalonia.Android
if(_pendingCallback)
return;
- if (_tick == null || _views.Count == 0)
+ if (_tick == null)
return;
_pendingCallback = true;
diff --git a/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs b/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs
index 5da78439e2..c89619749c 100644
--- a/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs
+++ b/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs
@@ -3,35 +3,48 @@ using Android.Content;
using Android.Content.Res;
using Android.Provider;
using Android.Views;
+using AndroidX.Core.Content;
using Avalonia.Input;
using Avalonia.Platform;
+using Avalonia.Threading;
using Color = Avalonia.Media.Color;
namespace Avalonia.Android.Platform;
-// TODO: ideally should be created per view/activity.
internal class AndroidPlatformSettings : DefaultPlatformSettings
{
- private PlatformColorValues _latestValues;
+ private PlatformColorValues _colorValues;
private TimeSpan _holdWaitDuration = TimeSpan.FromMilliseconds(300);
private TimeSpan _doubleTapTime = TimeSpan.FromMilliseconds(500);
private Size _doubleTapSize = new Size(16,16);
private Size _tapSize = new Size(10,10);
+ private string? _latestLanguage;
public AndroidPlatformSettings()
{
- _latestValues = base.GetColorValues();
if (global::Android.App.Application.Context is { } context)
{
- GetInputConfigValues(context);
+ UpdateInputConfigValues(context);
+ _colorValues = GetColorValuesFromContext(context);
+ _latestLanguage = QueryPreferredApplicationLanguage(context);
+
+ ContextCompat.RegisterReceiver(
+ context,
+ new ConfigurationChangedReceiver(this),
+ new IntentFilter(Intent.ActionConfigurationChanged),
+ ContextCompat.ReceiverNotExported);
}
+ else
+ _colorValues = base.GetColorValues();
}
public override PlatformColorValues GetColorValues()
{
- return _latestValues;
+ return _colorValues;
}
+ public override string PreferredApplicationLanguage => _latestLanguage ?? base.PreferredApplicationLanguage;
+
public override TimeSpan GetDoubleTapTime(PointerType type)
{
return type == PointerType.Mouse ? base.GetDoubleTapTime(type) : _doubleTapTime;
@@ -49,50 +62,69 @@ internal class AndroidPlatformSettings : DefaultPlatformSettings
public override TimeSpan HoldWaitDuration => _holdWaitDuration;
- internal void OnViewConfigurationChanged(Context context, Configuration configuration)
+ private void UpdateColorValues(Context context)
{
- if (context.Resources is null)
+ var oldColorValues = _colorValues;
+ var colorValues = GetColorValuesFromContext(context);
+
+ if (oldColorValues != colorValues)
{
- return;
+ _colorValues = colorValues;
+ OnColorValuesChanged(colorValues);
}
+ }
- PlatformThemeVariant systemTheme = (configuration.UiMode & UiMode.NightMask) switch
+ private void UpdatePreferredApplicationLanguage(Context context)
+ {
+ var oldLanguage = _latestLanguage;
+ var language = QueryPreferredApplicationLanguage(context);
+
+ if (oldLanguage != language)
{
- UiMode.NightYes => PlatformThemeVariant.Dark,
- UiMode.NightNo => PlatformThemeVariant.Light,
- _ => throw new ArgumentOutOfRangeException()
- };
+ _latestLanguage = language;
+ OnPreferredApplicationLanguageChanged();
+ }
+ }
+
+ private static PlatformColorValues GetColorValuesFromContext(Context context)
+ {
+ var uiMode = context.Resources?.Configuration?.UiMode & UiMode.NightMask ?? UiMode.NightNo;
+ var systemTheme = uiMode == UiMode.NightYes ? PlatformThemeVariant.Dark : PlatformThemeVariant.Light;
+ var contrastPreference = IsHighContrast(context);
if (OperatingSystem.IsAndroidVersionAtLeast(31))
{
- // See https://developer.android.com/reference/android/R.color
- var accent1 = context.Resources.GetColor(17170494, context.Theme); // Resource.Color.SystemAccent1500
- var accent2 = context.Resources.GetColor(17170507, context.Theme); // Resource.Color.SystemAccent2500
- var accent3 = context.Resources.GetColor(17170520, context.Theme); // Resource.Color.SystemAccent3500
-
- _latestValues = new PlatformColorValues
+ if (context.Resources is { } resources)
{
- ThemeVariant = systemTheme,
- ContrastPreference = IsHighContrast(context),
- AccentColor1 = new Color(accent1.A, accent1.R, accent1.G, accent1.B),
- AccentColor2 = new Color(accent2.A, accent2.R, accent2.G, accent2.B),
- AccentColor3 = new Color(accent3.A, accent3.R, accent3.G, accent3.B),
- };
+ // See https://developer.android.com/reference/android/R.color
+ var accent1 = resources.GetColor(17170494, context.Theme); // Resource.Color.SystemAccent1500
+ var accent2 = resources.GetColor(17170507, context.Theme); // Resource.Color.SystemAccent2500
+ var accent3 = resources.GetColor(17170520, context.Theme); // Resource.Color.SystemAccent3500
+
+ return new PlatformColorValues
+ {
+ ThemeVariant = systemTheme,
+ ContrastPreference = contrastPreference,
+ AccentColor1 = new Color(accent1.A, accent1.R, accent1.G, accent1.B),
+ AccentColor2 = new Color(accent2.A, accent2.R, accent2.G, accent2.B),
+ AccentColor3 = new Color(accent3.A, accent3.R, accent3.G, accent3.B),
+ };
+ }
}
else if (OperatingSystem.IsAndroidVersionAtLeast(23))
{
// See https://developer.android.com/reference/android/R.attr
- var array = context.Theme?.ObtainStyledAttributes(new[] { 16843829 }); // Resource.Attribute.ColorAccent
+ var array = context.Theme?.ObtainStyledAttributes([16843829]); // Resource.Attribute.ColorAccent
if (array is not null)
{
try
{
var accent = array.GetColor(0, 0);
- _latestValues = new PlatformColorValues
+ return new PlatformColorValues
{
ThemeVariant = systemTheme,
- ContrastPreference = IsHighContrast(context),
+ ContrastPreference = contrastPreference,
AccentColor1 = new Color(accent.A, accent.R, accent.G, accent.B)
};
}
@@ -102,17 +134,15 @@ internal class AndroidPlatformSettings : DefaultPlatformSettings
}
}
}
- else
- {
- _latestValues = _latestValues with { ThemeVariant = systemTheme };
- }
-
- GetInputConfigValues(context);
- OnColorValuesChanged(_latestValues);
+ return new PlatformColorValues
+ {
+ ThemeVariant = systemTheme,
+ ContrastPreference = contrastPreference
+ };
}
- private void GetInputConfigValues(Context context)
+ private void UpdateInputConfigValues(Context context)
{
_holdWaitDuration = TimeSpan.FromMilliseconds(ViewConfiguration.LongPressTimeout);
@@ -131,6 +161,12 @@ internal class AndroidPlatformSettings : DefaultPlatformSettings
}
}
+ private string? QueryPreferredApplicationLanguage(Context? context)
+ {
+ var locale = context?.Resources?.Configuration?.Locales?.Get(0);
+ return locale?.ToLanguageTag() is { Length: > 0 } tag ? tag : null;
+ }
+
private static ColorContrastPreference IsHighContrast(Context context)
{
try
@@ -143,4 +179,27 @@ internal class AndroidPlatformSettings : DefaultPlatformSettings
return ColorContrastPreference.NoPreference;
}
}
+
+ private sealed class ConfigurationChangedReceiver(AndroidPlatformSettings settings) : BroadcastReceiver
+ {
+ public override void OnReceive(Context? context, Intent? intent)
+ {
+ if (context is null)
+ return;
+
+ // The context might still have the old values at this point because they haven't been processed yet.
+ // Postpone the update 100ms arbitrarily. Not an ideal solution, but sufficient.
+ var timer = new DispatcherTimer(TimeSpan.FromMilliseconds(100), DispatcherPriority.Normal, Dispatcher.UIThread);
+
+ timer.Tick += (_, _) =>
+ {
+ timer.Stop();
+ settings.UpdateInputConfigValues(context);
+ settings.UpdateColorValues(context);
+ settings.UpdatePreferredApplicationLanguage(context);
+ };
+
+ timer.Start();
+ }
+ }
}
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index a732e90689..6209301146 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -30,6 +30,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
class TopLevelImpl : ITopLevelImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfoWithWaitPolicy
{
+ private readonly Context _context;
private readonly AndroidKeyboardEventsHelper _keyboardHelper;
private readonly AndroidMotionEventsHelper _pointerHelper;
private readonly AndroidInputMethod _textInputMethod;
@@ -51,6 +52,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
throw new ArgumentException("AvaloniaView.Context must not be null");
}
+ _context = context;
_view = new SurfaceViewImpl(context, this, placeOnTop);
_textInputMethod = new AndroidInputMethod(avaloniaView);
_keyboardHelper = new AndroidKeyboardEventsHelper(this);
@@ -245,22 +247,15 @@ namespace Avalonia.Android.Platform.SkiaPlatform
};
}
- // Sets the default app NightMode to AppCompatDelegate.ModeNightFollowSystem when themeVariant is null. This
- // allows app to follow the current OS night mode. Using either ModeNightNo or ModeNightYes will force the app
- // to use one night mode, ignoring the system's configuration and preventing us from detecting system theme changes
- // in View.OnConfigurationChanged. In this case, only Activity.OnConfigurationChanged is called when system theme is
- // changed, but we don't have access to that method if the toplevel view is embedded in a custom activity
- var nightMode = themeVariant == null ? AppCompatDelegate.ModeNightFollowSystem :
- themeVariant == PlatformThemeVariant.Light ? AppCompatDelegate.ModeNightNo : AppCompatDelegate.ModeNightYes;
-
- AppCompatDelegate.DefaultNightMode = nightMode;
-
- if (nightMode == AppCompatDelegate.ModeNightFollowSystem && _view?.Context is { } context
- && context.Resources?.Configuration is { } config)
+ if (_context is AppCompatActivity activity)
{
- var settings =
- AvaloniaLocator.Current.GetRequiredService() as AndroidPlatformSettings;
- settings?.OnViewConfigurationChanged(context, config);
+ var nightMode = themeVariant == PlatformThemeVariant.Dark ?
+ AppCompatDelegate.ModeNightYes :
+ AppCompatDelegate.ModeNightNo;
+
+ // Don't use AppCompatDelegate.DefaultNightMode: doing so will force the app to use one night mode,
+ // ignoring the system's configuration and preventing us from detecting system theme changes.
+ activity.Delegate.SetLocalNightMode(nightMode);
}
}
diff --git a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs
index e55689f93d..66e56f3d6b 100644
--- a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs
+++ b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs
@@ -7,6 +7,7 @@ using Android;
using Android.App;
using Android.Content;
using Android.Provider;
+using AndroidX.DocumentFile.Provider;
using Avalonia.Platform.Storage;
using Avalonia.Platform.Storage.FileIO;
using AndroidUri = Android.Net.Uri;
@@ -18,6 +19,8 @@ namespace Avalonia.Android.Platform.Storage;
internal class AndroidStorageProvider : IStorageProvider
{
public static ReadOnlySpan AndroidKey => "android"u8;
+ private const string ContentUriScheme = "content";
+ private const string FileUriScheme = "file";
private readonly Activity _activity;
public AndroidStorageProvider(Activity activity)
@@ -62,10 +65,29 @@ internal class AndroidStorageProvider : IStorageProvider
// to read or write files in your application-specific directories [...]"
// Consequently, we don't try to check for that permission here anymore.
- var javaFile = new JavaFile(androidUriPath);
- if (javaFile.Exists() && javaFile.IsFile)
+ if (filePath.Scheme == FileUriScheme && androidUri.Path is not null)
{
- return new BclStorageFile(new System.IO.FileInfo(javaFile.AbsolutePath));
+ var javaFile = new JavaFile(androidUri.Path);
+ if (javaFile.Exists() && javaFile.IsFile)
+ {
+ return new BclStorageFile(new System.IO.FileInfo(javaFile.AbsolutePath));
+ }
+ return null;
+ }
+ else if (filePath.Scheme == ContentUriScheme && _activity.ContentResolver is not null)
+ {
+ try
+ {
+ using var stream = _activity.ContentResolver.OpenInputStream(androidUri);
+ if (stream is not null)
+ {
+ return new AndroidStorageFile(_activity, androidUri);
+ }
+ }
+ catch (Exception)
+ {
+ return null;
+ }
}
return null;
@@ -89,10 +111,43 @@ internal class AndroidStorageProvider : IStorageProvider
return null;
}
- var javaFile = new JavaFile(androidUriPath);
- if (javaFile.Exists() && javaFile.IsDirectory)
+ if (folderPath.Scheme == FileUriScheme && androidUri.Path is not null)
+ {
+ var javaFile = new JavaFile(androidUri.Path);
+ if (javaFile.Exists() && javaFile.IsDirectory)
+ {
+ return new BclStorageFolder(new System.IO.DirectoryInfo(javaFile.AbsolutePath));
+ }
+ return null;
+ }
+ else if (folderPath.Scheme == ContentUriScheme)
{
- return new BclStorageFolder(new System.IO.DirectoryInfo(javaFile.AbsolutePath));
+ try
+ {
+ if (OperatingSystem.IsAndroidVersionAtLeast(21))
+ {
+ if (DocumentsContract.IsTreeUri(androidUri))
+ {
+ var docId = DocumentsContract.GetTreeDocumentId(androidUri);
+ if (!string.IsNullOrEmpty(docId))
+ {
+ return new AndroidStorageFolder(_activity, androidUri, false);
+ }
+ }
+ else
+ {
+ var documentFile = DocumentFile.FromSingleUri(_activity, androidUri);
+ if (documentFile is not null && documentFile.Exists() && documentFile.IsDirectory)
+ {
+ return new AndroidStorageFolder(_activity, androidUri, false);
+ }
+ }
+ }
+ }
+ catch (Exception)
+ {
+ return null;
+ }
}
return null;
diff --git a/src/Avalonia.Base/Animation/AnimationInstance`1.cs b/src/Avalonia.Base/Animation/AnimationInstance`1.cs
index f1b0a937a4..cdfa1f9dda 100644
--- a/src/Avalonia.Base/Animation/AnimationInstance`1.cs
+++ b/src/Avalonia.Base/Animation/AnimationInstance`1.cs
@@ -15,6 +15,7 @@ namespace Avalonia.Animation
private readonly Animator _animator;
private readonly Animation _animation;
private readonly Animatable _targetControl;
+ private readonly Visual? _visualTarget;
private readonly Action? _onCompleteAction;
private IDisposable? _timerSub;
private EventHandler? _propertyChangedDelegate;
@@ -61,7 +62,8 @@ namespace Avalonia.Animation
private readonly bool _shouldPauseOnInvisible;
- public AnimationInstance(Animation animation, Animatable control, Animator animator, IClock baseClock, Action? OnComplete, Func Interpolator, bool shouldPauseOnInvisible)
+ public AnimationInstance(Animation animation, Animatable control, Animator animator, IClock baseClock,
+ Action? OnComplete, Func Interpolator, bool shouldPauseOnInvisible, Visual? visualTarget)
{
_lastInterpValue = default!;
_animator = animator;
@@ -70,6 +72,7 @@ namespace Avalonia.Animation
_onCompleteAction = OnComplete;
_interpolator = Interpolator;
_baseClock = baseClock;
+ _visualTarget = visualTarget;
_initialKFValue = default!;
_neutralValue = default!;
_shouldPauseOnInvisible = shouldPauseOnInvisible;
@@ -132,7 +135,7 @@ namespace Avalonia.Animation
_targetControl.PropertyChanged -= _propertyChangedDelegate;
timerSub.Dispose();
- if (_targetControl is Visual visual)
+ if (_visualTarget is { } visual)
{
if (_visibilityChangedHandler is not null)
{
@@ -155,7 +158,7 @@ namespace Avalonia.Animation
_clock = new Clock(_baseClock);
_timerSub = _clock.Subscribe(Step);
- if (_targetControl is Visual visual)
+ if (_visualTarget is { } visual)
{
if (_shouldPauseOnInvisible)
{
diff --git a/src/Avalonia.Base/Animation/Animators/Animator`1.cs b/src/Avalonia.Base/Animation/Animators/Animator`1.cs
index 20311c8389..88446fe533 100644
--- a/src/Avalonia.Base/Animation/Animators/Animator`1.cs
+++ b/src/Avalonia.Base/Animation/Animators/Animator`1.cs
@@ -18,8 +18,19 @@ namespace Avalonia.Animation.Animators
///
public virtual IDisposable? Apply(Animation animation, Animatable control, IClock? clock, IObservable match, Action? onComplete, bool shouldPauseOnInvisible)
+ => Apply(animation, control, clock, match, onComplete, shouldPauseOnInvisible, control as Visual);
+
+ internal IDisposable? Apply(Animation animation, Animatable control, IClock? clock, IObservable match,
+ Action? onComplete, bool shouldPauseOnInvisible, Visual? visualTarget)
{
- var subject = new DisposeAnimationInstanceSubject(this, animation, control, clock, onComplete, shouldPauseOnInvisible);
+ var subject = new DisposeAnimationInstanceSubject(
+ this,
+ animation,
+ control,
+ clock,
+ onComplete,
+ shouldPauseOnInvisible,
+ visualTarget);
return new CompositeDisposable(match.Subscribe(subject), subject);
}
@@ -103,7 +114,8 @@ namespace Avalonia.Animation.Animators
///
/// Runs the KeyFrames Animation.
///
- internal IDisposable Run(Animation animation, Animatable control, IClock? clock, Action? onComplete, bool shouldPauseOnInvisible)
+ internal IDisposable Run(Animation animation, Animatable control, IClock? clock, Action? onComplete,
+ bool shouldPauseOnInvisible, Visual? visualTarget)
{
var instance = new AnimationInstance(
animation,
@@ -112,7 +124,8 @@ namespace Avalonia.Animation.Animators
clock ?? control.Clock ?? Clock.GlobalClock,
onComplete,
InterpolationHandler,
- shouldPauseOnInvisible);
+ shouldPauseOnInvisible,
+ visualTarget);
return BindAnimation(control, instance);
}
diff --git a/src/Avalonia.Base/Animation/Animators/TransformAnimator.cs b/src/Avalonia.Base/Animation/Animators/TransformAnimator.cs
index aef5c78f95..260a2a71ab 100644
--- a/src/Avalonia.Base/Animation/Animators/TransformAnimator.cs
+++ b/src/Avalonia.Base/Animation/Animators/TransformAnimator.cs
@@ -67,7 +67,7 @@ namespace Avalonia.Animation.Animators
if (renderTransformType == Property.OwnerType)
{
return _doubleAnimator.Apply(animation, (Transform) ctrl.RenderTransform, clock ?? control.Clock,
- obsMatch, onComplete, shouldPauseOnInvisible);
+ obsMatch, onComplete, shouldPauseOnInvisible, ctrl);
}
// It's a TransformGroup and try finding the target there.
else if (renderTransformType == typeof(TransformGroup))
@@ -77,7 +77,7 @@ namespace Avalonia.Animation.Animators
if (transform.GetType() == Property.OwnerType)
{
return _doubleAnimator.Apply(animation, transform, clock ?? control.Clock,
- obsMatch, onComplete, shouldPauseOnInvisible);
+ obsMatch, onComplete, shouldPauseOnInvisible, ctrl);
}
}
}
diff --git a/src/Avalonia.Base/Animation/CrossFade.cs b/src/Avalonia.Base/Animation/CrossFade.cs
index 45a4300e5b..33641e4edc 100644
--- a/src/Avalonia.Base/Animation/CrossFade.cs
+++ b/src/Avalonia.Base/Animation/CrossFade.cs
@@ -260,9 +260,7 @@ namespace Avalonia.Animation
return FarPeekOpacity;
}
- private static double Lerp(double from, double to, double t)
- {
- return from + ((to - from) * Math.Clamp(t, 0.0, 1.0));
- }
+ private static double Lerp(double from, double to, double t) =>
+ double.Lerp(from, to, Math.Clamp(t, 0.0, 1.0));
}
}
diff --git a/src/Avalonia.Base/Animation/DisposeAnimationInstanceSubject.cs b/src/Avalonia.Base/Animation/DisposeAnimationInstanceSubject.cs
index 7d355cc77c..36ec54127c 100644
--- a/src/Avalonia.Base/Animation/DisposeAnimationInstanceSubject.cs
+++ b/src/Avalonia.Base/Animation/DisposeAnimationInstanceSubject.cs
@@ -12,7 +12,8 @@ namespace Avalonia.Animation
Animatable control,
IClock? clock,
Action? onComplete,
- bool shouldPauseOnInvisible)
+ bool shouldPauseOnInvisible,
+ Visual? visualTarget)
: IObserver, IDisposable
{
private IDisposable? _lastInstance;
@@ -41,7 +42,13 @@ namespace Avalonia.Animation
if (matchVal)
{
- _lastInstance = animator.Run(animation, control, clock, onComplete, shouldPauseOnInvisible);
+ _lastInstance = animator.Run(
+ animation,
+ control,
+ clock,
+ onComplete,
+ shouldPauseOnInvisible,
+ visualTarget);
}
else
{
diff --git a/src/Avalonia.Base/Animation/Transitions/Rotate3DTransition.cs b/src/Avalonia.Base/Animation/Transitions/Rotate3DTransition.cs
index 41aa205547..38e4a46dc9 100644
--- a/src/Avalonia.Base/Animation/Transitions/Rotate3DTransition.cs
+++ b/src/Avalonia.Base/Animation/Transitions/Rotate3DTransition.cs
@@ -244,10 +244,8 @@ public class Rotate3DTransition : PageSlide
return 1;
}
- private static double Lerp(double from, double to, double t)
- {
- return from + ((to - from) * Math.Clamp(t, 0.0, 1.0));
- }
+ private static double Lerp(double from, double to, double t) =>
+ double.Lerp(from, to, Math.Clamp(t, 0.0, 1.0));
///
public override void Reset(Visual visual)
diff --git a/src/Avalonia.Base/Data/Converters/ObjectConverters.cs b/src/Avalonia.Base/Data/Converters/ObjectConverters.cs
index 8496ee1ae6..bfec53c3f6 100644
--- a/src/Avalonia.Base/Data/Converters/ObjectConverters.cs
+++ b/src/Avalonia.Base/Data/Converters/ObjectConverters.cs
@@ -1,3 +1,6 @@
+using System.Linq;
+using System.Collections.Generic;
+
namespace Avalonia.Data.Converters
{
///
@@ -28,5 +31,52 @@ namespace Avalonia.Data.Converters
///
public static readonly IValueConverter NotEqual =
new FuncValueConverter((a, b) => !a?.Equals(b) ?? b is not null);
+
+ ///
+ /// A multi-value converter that returns true if all inputs are null.
+ ///
+ public static readonly IMultiValueConverter AreAllNull =
+ new FuncMultiValueConverter(x => x.All(item => item is null));
+
+ ///
+ /// A multi-value converter that returns true if at least one input is null.
+ ///
+ public static readonly IMultiValueConverter AreAnyNull =
+ new FuncMultiValueConverter(x => x.Any(item => item is null));
+
+ ///
+ /// A multi-value converter that returns true if all inputs are equal to each other.
+ /// Null values are not considered equal to anything since they don't have Equals method.
+ ///
+ public static readonly IMultiValueConverter AreAllEqual =
+ new FuncMultiValueConverter(EqualityFunction);
+
+ ///
+ /// Helper function for AreAllEqual converter. Returns true if all inputs are equal to each other.
+ ///
+ /// The values to compare.
+ /// True if all values are equal, false otherwise.
+ private static bool EqualityFunction(IEnumerable values)
+ {
+ using var enumerator = values.GetEnumerator();
+
+ //Empty collection is considered equal.
+ if (!enumerator.MoveNext())
+ return true;
+
+ //Null values are not considered equal to anything since they don't have Equals method.
+ var first = enumerator.Current;
+ if (first is null)
+ return false;
+
+ while (enumerator.MoveNext())
+ {
+ var item = enumerator.Current;
+ if (item is null || !item.Equals(first))
+ return false;
+ }
+
+ return true;
+ }
}
}
diff --git a/src/Avalonia.Base/GeneratedAttachedPropertyAttribute.cs b/src/Avalonia.Base/GeneratedAttachedPropertyAttribute.cs
new file mode 100644
index 0000000000..32afd0c8e9
--- /dev/null
+++ b/src/Avalonia.Base/GeneratedAttachedPropertyAttribute.cs
@@ -0,0 +1,60 @@
+using System;
+using Avalonia.Data;
+
+namespace Avalonia;
+
+///
+/// Instructs the Avalonia property source generator to emit an
+/// registration and accessor methods for the annotated partial Get method.
+///
+///
+///
+/// Apply to a static partial T Get{Name}(THost element) method declared on a partial class.
+///
+///
+[AttributeUsage(AttributeTargets.Method, Inherited = false)]
+public sealed class GeneratedAttachedPropertyAttribute : Attribute
+{
+ ///
+ /// Re-owns an existing attached property from the specified base type instead of registering a new property.
+ /// The source property must be a static {Name}Property member of the given type.
+ /// Metadata may still be overridden with , and .
+ ///
+ public Type? AddOwnerFrom { get; set; }
+
+ ///
+ /// The default value of the property. Must be a compile-time constant.
+ /// For non-constant defaults, call {Name}Property.OverrideDefaultValue(...) in a static constructor instead.
+ ///
+ public object? DefaultValue { get; set; }
+
+ ///
+ /// The default binding mode for the property.
+ ///
+ public BindingMode DefaultBindingMode { get; set; }
+
+ ///
+ /// Whether the property inherits its value down the logical tree.
+ ///
+ ///
+ /// Cannot be used with .
+ ///
+ public bool Inherits { get; set; }
+
+ ///
+ /// The name of the validation method, with signature
+ /// static bool {Method}(T value). Pass via nameof(...).
+ /// Declare it as an private static method on the same type.
+ ///
+ ///
+ /// Cannot be used with .
+ ///
+ public string? ValidateMethodName { get; set; }
+
+ ///
+ /// The name of the coercion method, with signature
+ /// static T {Method}(AvaloniaObject sender, T value).
+ /// Declare it as an private static method on the same type.
+ ///
+ public string? CoerceMethodName { get; set; }
+}
diff --git a/src/Avalonia.Base/GeneratedDirectPropertyAttribute.cs b/src/Avalonia.Base/GeneratedDirectPropertyAttribute.cs
new file mode 100644
index 0000000000..3cf16589a7
--- /dev/null
+++ b/src/Avalonia.Base/GeneratedDirectPropertyAttribute.cs
@@ -0,0 +1,41 @@
+using System;
+using Avalonia.Data;
+
+namespace Avalonia;
+
+///
+/// Instructs the Avalonia property source generator to emit a
+/// registration and accessor bodies for the annotated partial property.
+///
+///
+///
+/// Apply to a partial instance property with both get and set accessors,
+/// declared on a partial class deriving from .
+///
+///
+[AttributeUsage(AttributeTargets.Property, Inherited = false)]
+public sealed class GeneratedDirectPropertyAttribute : Attribute
+{
+ ///
+ /// Re-owns an existing direct property from the specified base type instead of registering a new property.
+ /// The source property must be a static {Name}Property member of the given type.
+ ///
+ public Type? AddOwnerFrom { get; set; }
+
+ ///
+ /// The value returned when the property is cleared (e.g. by ClearValue)
+ /// or when a binding produces an invalid value.
+ /// The initial value of the property comes from the property initializer.
+ ///
+ public object? UnsetValue { get; set; }
+
+ ///
+ /// The default binding mode for the property.
+ ///
+ public BindingMode DefaultBindingMode { get; set; }
+
+ ///
+ /// Whether the property is interested in data validation.
+ ///
+ public bool EnableDataValidation { get; set; }
+}
diff --git a/src/Avalonia.Base/GeneratedStyledPropertyAttribute.cs b/src/Avalonia.Base/GeneratedStyledPropertyAttribute.cs
new file mode 100644
index 0000000000..97234e57d4
--- /dev/null
+++ b/src/Avalonia.Base/GeneratedStyledPropertyAttribute.cs
@@ -0,0 +1,66 @@
+using System;
+using Avalonia.Data;
+
+namespace Avalonia;
+
+///
+/// Instructs the Avalonia property source generator to emit a
+/// registration and accessor bodies for the annotated partial property.
+///
+///
+///
+/// Apply to a partial instance property with both get and set accessors,
+/// declared on a partial class deriving from .
+///
+///
+[AttributeUsage(AttributeTargets.Property, Inherited = false)]
+public sealed class GeneratedStyledPropertyAttribute : Attribute
+{
+ ///
+ /// Re-owns an existing styled property from the specified base type instead of registering a new property.
+ /// The source property must be a static {Name}Property member of the given type.
+ /// Metadata may still be overridden with , and .
+ ///
+ public Type? AddOwnerFrom { get; set; }
+
+ ///
+ /// The default value of the property. Must be a compile-time constant.
+ /// For non-constant defaults, call {Name}Property.OverrideDefaultValue(...) in a static constructor instead.
+ ///
+ public object? DefaultValue { get; set; }
+
+ ///
+ /// The default binding mode for the property.
+ ///
+ public BindingMode DefaultBindingMode { get; set; }
+
+ ///
+ /// Whether the property inherits its value down the logical tree.
+ ///
+ ///
+ /// Cannot be used with .
+ ///
+ public bool Inherits { get; set; }
+
+ ///
+ /// Whether the property is interested in data validation.
+ ///
+ public bool EnableDataValidation { get; set; }
+
+ ///
+ /// The name of the validation method, with signature
+ /// static bool {Method}(T value).
+ /// Declare it as an private static method on the same type.
+ ///
+ ///
+ /// Cannot be used with .
+ ///
+ public string? ValidateMethodName { get; set; }
+
+ ///
+ /// The name of the coercion method, with signature
+ /// static T {Method}(AvaloniaObject sender, T value).
+ /// Declare it as an private static method on the same type.
+ ///
+ public string? CoerceMethodName { get; set; }
+}
diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs
index 0acc043eec..340a006ed1 100644
--- a/src/Avalonia.Base/Input/MouseDevice.cs
+++ b/src/Avalonia.Base/Input/MouseDevice.cs
@@ -18,6 +18,8 @@ namespace Avalonia.Input
private static MouseDevice? _primary;
internal static MouseDevice Primary => _primary ??= new MouseDevice();
+ internal static void ResetPrimaryForUnitTests() => _primary = null;
+
private int _clickCount;
private Rect _lastClickRect;
private ulong _lastClickTime;
@@ -218,9 +220,7 @@ namespace Avalonia.Input
}
finally
{
- _pointer.Capture(null, CaptureSource.Implicit);
- _pointer.CaptureGestureRecognizer(null);
- _pointer.IsGestureRecognitionSkipped = false;
+ _pointer.CaptureLost(CaptureSource.Implicit);
_lastMouseDownButton = default;
}
return e.Handled;
diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs
index f7211ea351..b7dba977d5 100644
--- a/src/Avalonia.Base/Input/PenDevice.cs
+++ b/src/Avalonia.Base/Input/PenDevice.cs
@@ -63,6 +63,9 @@ namespace Avalonia.Input
case RawPointerEventType.LeaveWindow:
shouldReleasePointer = true;
break;
+ case RawPointerEventType.CancelCapture:
+ pointer.PlatformCaptureLost();
+ break;
case RawPointerEventType.LeftButtonDown:
case RawPointerEventType.RightButtonDown:
case RawPointerEventType.MiddleButtonDown:
@@ -90,8 +93,8 @@ namespace Avalonia.Input
{
if (shouldReleasePointer)
{
- pointer.Dispose();
_pointers.Remove(e.RawPointerId);
+ pointer.Dispose();
}
}
}
@@ -173,9 +176,7 @@ namespace Avalonia.Input
}
finally
{
- pointer.Capture(null, CaptureSource.Implicit);
- pointer.CaptureGestureRecognizer(null);
- pointer.IsGestureRecognitionSkipped = false;
+ pointer.CaptureLost(CaptureSource.Implicit);
_lastMouseDownButton = default;
}
diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs
index 9b751baf12..47aab499ce 100644
--- a/src/Avalonia.Base/Input/Pointer.cs
+++ b/src/Avalonia.Base/Input/Pointer.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using Avalonia.Input.GestureRecognizers;
using Avalonia.VisualTree;
@@ -18,6 +19,8 @@ namespace Avalonia.Input
private static int s_NextFreePointerId = 1000;
public static int GetNextFreeId() => s_NextFreePointerId++;
+ private bool _disposed;
+
public Pointer(int id, PointerType type, bool isPrimary)
{
Id = id;
@@ -40,10 +43,25 @@ namespace Avalonia.Input
}
- internal void PlatformCaptureLost()
+ internal void PlatformCaptureLost() => CaptureLost(CaptureSource.Platform);
+
+ ///
+ /// Ends every capture the pointer holds, on the element and on a gesture recognizer.
+ ///
+ internal void CaptureLost(CaptureSource source)
+ {
+ if (_disposed)
+ return;
+
+ CaptureLostCore(source);
+ }
+
+ private void CaptureLostCore(CaptureSource source)
{
if (Captured != null)
- Capture(null, CaptureSource.Platform);
+ CaptureCore(null, source);
+ CaptureGestureRecognizerCore(null);
+ IsGestureRecognitionSkipped = false;
}
public void Capture(IInputElement? control)
@@ -52,6 +70,17 @@ namespace Avalonia.Input
}
internal void Capture(IInputElement? control, CaptureSource source)
+ {
+ if (_disposed)
+ {
+ Debug.Assert(control is null, "Capturing a pointer that no longer exists.");
+ return;
+ }
+
+ CaptureCore(control, source);
+ }
+
+ private void CaptureCore(IInputElement? control, CaptureSource source)
{
var oldCapture = Captured;
var oldSource = CaptureSource;
@@ -148,7 +177,14 @@ namespace Avalonia.Input
public void Dispose()
{
- // callers are responsible for calling Capture(null, source) with an appropriate source
+ if (_disposed)
+ return;
+
+ // Mark the pointer gone first, so a capture lost handler can't capture it again.
+ // It no longer exists, so the platform is the only source the release can come from.
+ _disposed = true;
+
+ CaptureLostCore(CaptureSource.Platform);
}
///
@@ -156,6 +192,17 @@ namespace Avalonia.Input
///
/// The gesture recognizer.
internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer)
+ {
+ if (_disposed)
+ {
+ Debug.Assert(gestureRecognizer is null, "Capturing a pointer that no longer exists to a gesture recognizer.");
+ return;
+ }
+
+ CaptureGestureRecognizerCore(gestureRecognizer);
+ }
+
+ private void CaptureGestureRecognizerCore(GestureRecognizer? gestureRecognizer)
{
if (CapturedGestureRecognizer != gestureRecognizer)
{
diff --git a/src/Avalonia.Base/Input/TouchDevice.cs b/src/Avalonia.Base/Input/TouchDevice.cs
index 6429d9c0fc..dac12dedd8 100644
--- a/src/Avalonia.Base/Input/TouchDevice.cs
+++ b/src/Avalonia.Base/Input/TouchDevice.cs
@@ -109,20 +109,14 @@ namespace Avalonia.Input
{
target.RaiseEvent(e);
}
- pointer?.Capture(null, CaptureSource.Implicit);
+ pointer?.CaptureLost(CaptureSource.Implicit);
}
}
if (args.Type == RawPointerEventType.TouchCancel)
{
_pointers.Remove(args.RawPointerId);
- using (pointer)
- {
- pointer?.Capture(null, CaptureSource.Platform);
- pointer?.CaptureGestureRecognizer(null);
- if (pointer != null)
- pointer.IsGestureRecognitionSkipped = false;
- }
+ pointer?.Dispose();
}
if (args.Type == RawPointerEventType.TouchUpdate)
@@ -165,7 +159,7 @@ namespace Avalonia.Input
internal void PlatformCaptureLost()
{
foreach (var pointer in _pointers.Values)
- pointer.Capture(null);
+ pointer.PlatformCaptureLost();
}
}
}
diff --git a/src/Avalonia.Base/Layout/Layoutable.cs b/src/Avalonia.Base/Layout/Layoutable.cs
index e526dec046..170b52491e 100644
--- a/src/Avalonia.Base/Layout/Layoutable.cs
+++ b/src/Avalonia.Base/Layout/Layoutable.cs
@@ -543,6 +543,8 @@ namespace Avalonia.Layout
///
protected virtual Size MeasureCore(Size availableSize)
{
+ ApplyStyling();
+
if (IsVisible)
{
var margin = Margin;
@@ -555,7 +557,6 @@ namespace Avalonia.Layout
margin = LayoutHelper.RoundLayoutThickness(margin, scale);
}
- ApplyStyling();
ApplyTemplate();
var minMax = new MinMax(this);
diff --git a/src/Avalonia.Base/Media/Color.cs b/src/Avalonia.Base/Media/Color.cs
index ae16c30320..624513f065 100644
--- a/src/Avalonia.Base/Media/Color.cs
+++ b/src/Avalonia.Base/Media/Color.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Media
#if !BUILDTASK
public
#endif
- readonly struct Color : IEquatable
+ readonly struct Color : IEquatable, IFormattable
{
private const double byteToDouble = 1.0 / 255;
@@ -461,6 +461,97 @@ namespace Avalonia.Media
}
}
+ ///
+ /// Returns a formatted string representation of the color.
+ ///
+ ///
+ /// The format specifier. All color types support all specifiers via auto-conversion.
+ /// Uppercase includes alpha, lowercase excludes it. % suffix = percent mode:
+ ///
+ /// - null or "" — Default (known name or #aarrggbb)
+ /// - "X" — XAML hex with alpha: #AARRGGBB
+ /// - "x" — Hex without alpha: #RRGGBB
+ /// - "H" — HTML hex with alpha: #RRGGBBAA
+ /// - "R" — CSS rgba absolute: rgba(r, g, b, a)
+ /// - "r" — CSS rgb absolute: rgb(r, g, b)
+ /// - "R%" — CSS rgba percent: rgba(r%, g%, b%, a%)
+ /// - "r%" — CSS rgb percent: rgb(r%, g%, b%)
+ /// - "L"/"l"/"L%"/"l%" — CSS hsl/hsla (auto-converts to HSL)
+ /// - "V"/"v"/"V%"/"v%" — CSS hsv/hsva (auto-converts to HSV)
+ ///
+ /// "C" and "A" are reserved for future complex format strings.
+ ///
+ /// Ignored. Color formatting is culture-invariant.
+ /// The formatted string representation.
+ /// Thrown when is not recognized.
+ public string ToString(string? format, IFormatProvider? formatProvider)
+ {
+ if (string.IsNullOrEmpty(format))
+ {
+ return ToString();
+ }
+
+ return format switch
+ {
+ "X" => $"#{A:X2}{R:X2}{G:X2}{B:X2}",
+ "x" => $"#{R:X2}{G:X2}{B:X2}",
+ "H" => $"#{R:X2}{G:X2}{B:X2}{A:X2}",
+
+ "R" => FormatRgbCss(),
+ "r" => FormatRgbCss(includeAlpha: false),
+ "R%" => FormatRgbPercentCss(),
+ "r%" => FormatRgbPercentCss(includeAlpha: false),
+
+ "L" or "l" or "L%" or "l%" => ToHsl().ToString(format, formatProvider),
+ "V" or "v" or "V%" or "v%" => ToHsv().ToString(format, formatProvider),
+
+ _ => throw new FormatException($"Format string '{format}' is not supported.")
+ };
+ }
+
+ ///
+ /// Formats the color as a CSS rgb() or rgba() string using absolute RGB components and fractional alpha.
+ ///
+ private string FormatRgbCss(bool includeAlpha = true)
+ {
+ if (includeAlpha)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "rgba({0}, {1}, {2}, {3:F2})",
+ R,
+ G,
+ B,
+ A * byteToDouble);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "rgb({0}, {1}, {2})", R, G, B);
+ }
+
+ ///
+ /// Formats the color as a CSS rgb() or rgba() string with all components as percentages.
+ ///
+ private string FormatRgbPercentCss(bool includeAlpha = true)
+ {
+ int rPct = (int)Math.Round(R * byteToDouble * 100.0);
+ int gPct = (int)Math.Round(G * byteToDouble * 100.0);
+ int bPct = (int)Math.Round(B * byteToDouble * 100.0);
+
+ if (includeAlpha)
+ {
+ int aPct = (int)Math.Round(A * byteToDouble * 100.0);
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "rgba({0}%, {1}%, {2}%, {3}%)",
+ rPct,
+ gPct,
+ bPct,
+ aPct);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "rgb({0}%, {1}%, {2}%)", rPct, gPct, bPct);
+ }
+
///
/// Returns the integer representation of the color.
///
diff --git a/src/Avalonia.Base/Media/GeometryBuilder.cs b/src/Avalonia.Base/Media/GeometryBuilder.cs
index 074c48d8ee..2f65827f7b 100644
--- a/src/Avalonia.Base/Media/GeometryBuilder.cs
+++ b/src/Avalonia.Base/Media/GeometryBuilder.cs
@@ -20,7 +20,6 @@ namespace Avalonia.Media
///
internal class GeometryBuilder
{
- private const double PiOver2 = 1.57079633; // 90 deg to rad
private const double Epsilon = 0.00000153; // Same as LayoutHelper.LayoutEpsilon
///
@@ -157,7 +156,7 @@ namespace Avalonia.Media
context.ArcTo(
new Point(rect.Right, rect.Top + radiusY),
arcSize,
- rotationAngle: PiOver2,
+ rotationAngle: 0.0,
isLargeArc: false,
SweepDirection.Clockwise);
@@ -166,7 +165,7 @@ namespace Avalonia.Media
context.ArcTo(
new Point(rect.Right - radiusX, rect.Bottom),
arcSize,
- rotationAngle: PiOver2,
+ rotationAngle: 0.0,
isLargeArc: false,
SweepDirection.Clockwise);
@@ -175,7 +174,7 @@ namespace Avalonia.Media
context.ArcTo(
new Point(rect.Left, rect.Bottom - radiusY),
arcSize,
- rotationAngle: PiOver2,
+ rotationAngle: 0.0,
isLargeArc: false,
SweepDirection.Clockwise);
@@ -184,7 +183,7 @@ namespace Avalonia.Media
context.ArcTo(
new Point(rect.Left + radiusX, rect.Top),
arcSize,
- rotationAngle: PiOver2,
+ rotationAngle: 0.0,
isLargeArc: false,
SweepDirection.Clockwise);
diff --git a/src/Avalonia.Base/Media/HslColor.cs b/src/Avalonia.Base/Media/HslColor.cs
index 02176d65d7..2a09575d69 100644
--- a/src/Avalonia.Base/Media/HslColor.cs
+++ b/src/Avalonia.Base/Media/HslColor.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Media
#if !BUILDTASK
public
#endif
- readonly struct HslColor : IEquatable
+ readonly struct HslColor : IEquatable, IFormattable
{
///
/// Initializes a new instance of the struct.
@@ -177,6 +177,99 @@ namespace Avalonia.Media
return HslColor.ToHsv(H, S, L, A);
}
+ ///
+ /// Returns a formatted string representation of the HSL color.
+ ///
+ ///
+ /// The format specifier. All color types support all specifiers via auto-conversion.
+ /// Uppercase includes alpha, lowercase excludes it. % suffix = percent mode.
+ ///
+ /// - null or "" — Default (full-precision hsla(h, s, l, a))
+ /// - "X" — XAML hex: #AARRGGBB
+ /// - "x" — Hex: #RRGGBB
+ /// - "H" — HTML hex: #RRGGBBAA
+ /// - "R"/"r"/"R%"/"r%" — CSS rgb/rgba (auto-converts to RGB)
+ /// - "L" — CSS hsla: hsla(h, s%, l%, a)
+ /// - "l" — CSS hsl: hsl(h, s%, l%)
+ /// - "L%" — All percent: hsla(h%, s%, l%, a%)
+ /// - "l%" — All percent: hsl(h%, s%, l%)
+ /// - "V"/"v"/"V%"/"v%" — CSS hsv/hsva (auto-converts to HSV)
+ ///
+ /// "C" and "A" are reserved for future complex format strings.
+ ///
+ /// Ignored. Color formatting is culture-invariant.
+ /// The formatted string representation.
+ /// Thrown when is not recognized.
+ public string ToString(string? format, IFormatProvider? formatProvider)
+ {
+ if (string.IsNullOrEmpty(format))
+ {
+ return ToString();
+ }
+
+ return format switch
+ {
+ "X" or "x" or "H" or "R" or "r" or "R%" or "r%" => ToRgb().ToString(format, formatProvider),
+
+ "L" => FormatHslCss(),
+ "l" => FormatHslCss(includeAlpha: false),
+ "L%" => FormatHslPercentCss(),
+ "l%" => FormatHslPercentCss(includeAlpha: false),
+
+ "V" or "v" or "V%" or "v%" => ToHsv().ToString(format, formatProvider),
+
+ _ => throw new FormatException($"Format string '{format}' is not supported.")
+ };
+ }
+
+ ///
+ /// Formats the color as a CSS hsl() or hsla() string using degrees, percent saturation/lightness,
+ /// and fractional alpha.
+ ///
+ private string FormatHslCss(bool includeAlpha = true)
+ {
+ int hDeg = (int)Math.Round(H);
+ int sPct = (int)Math.Round(S * 100.0);
+ int lPct = (int)Math.Round(L * 100.0);
+
+ if (includeAlpha)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "hsla({0}, {1}%, {2}%, {3:F2})",
+ hDeg,
+ sPct,
+ lPct,
+ A);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "hsl({0}, {1}%, {2}%)", hDeg, sPct, lPct);
+ }
+
+ ///
+ /// Formats the color as a CSS hsl() or hsla() string with all components as percentages.
+ ///
+ private string FormatHslPercentCss(bool includeAlpha = true)
+ {
+ int hPct = (int)Math.Round(H / 360.0 * 100.0);
+ int sPct = (int)Math.Round(S * 100.0);
+ int lPct = (int)Math.Round(L * 100.0);
+
+ if (includeAlpha)
+ {
+ int aPct = (int)Math.Round(A * 100.0);
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "hsla({0}%, {1}%, {2}%, {3}%)",
+ hPct,
+ sPct,
+ lPct,
+ aPct);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "hsl({0}%, {1}%, {2}%)", hPct, sPct, lPct);
+ }
+
///
public override string ToString()
{
@@ -193,7 +286,7 @@ namespace Avalonia.Media
// hsla(230, 1.0, 0.5, 1.0)
//
- sb.Append("hsva(");
+ sb.Append("hsla(");
sb.Append(H.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(S.ToString(CultureInfo.InvariantCulture));
diff --git a/src/Avalonia.Base/Media/HsvColor.cs b/src/Avalonia.Base/Media/HsvColor.cs
index 03949d32aa..7ff180c8c5 100644
--- a/src/Avalonia.Base/Media/HsvColor.cs
+++ b/src/Avalonia.Base/Media/HsvColor.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Media
#if !BUILDTASK
public
#endif
- readonly struct HsvColor : IEquatable
+ readonly struct HsvColor : IEquatable, IFormattable
{
///
/// Initializes a new instance of the struct.
@@ -207,6 +207,99 @@ namespace Avalonia.Media
return HsvColor.ToHsl(H, S, V, A);
}
+ ///
+ /// Returns a formatted string representation of the HSV color.
+ ///
+ ///
+ /// The format specifier. All color types support all specifiers via auto-conversion.
+ /// Uppercase includes alpha, lowercase excludes it. % suffix = percent mode.
+ ///
+ /// - null or "" — Default (full-precision hsva(h, s, v, a))
+ /// - "X" — XAML hex: #AARRGGBB
+ /// - "x" — Hex: #RRGGBB
+ /// - "H" — HTML hex: #RRGGBBAA
+ /// - "R"/"r"/"R%"/"r%" — CSS rgb/rgba (auto-converts to RGB)
+ /// - "L"/"l"/"L%"/"l%" — CSS hsl/hsla (auto-converts to HSL)
+ /// - "V" — CSS hsva: hsva(h, s%, v%, a)
+ /// - "v" — CSS hsv: hsv(h, s%, v%)
+ /// - "V%" — All percent: hsva(h%, s%, v%, a%)
+ /// - "v%" — All percent: hsv(h%, s%, v%)
+ ///
+ /// "C" and "A" are reserved for future complex format strings.
+ ///
+ /// Ignored. Color formatting is culture-invariant.
+ /// The formatted string representation.
+ /// Thrown when is not recognized.
+ public string ToString(string? format, IFormatProvider? formatProvider)
+ {
+ if (string.IsNullOrEmpty(format))
+ {
+ return ToString();
+ }
+
+ return format switch
+ {
+ "X" or "x" or "H" or "R" or "r" or "R%" or "r%" => ToRgb().ToString(format, formatProvider),
+
+ "L" or "l" or "L%" or "l%" => ToHsl().ToString(format, formatProvider),
+
+ "V" => FormatHsvCss(),
+ "v" => FormatHsvCss(includeAlpha: false),
+ "V%" => FormatHsvPercentCss(),
+ "v%" => FormatHsvPercentCss(includeAlpha: false),
+
+ _ => throw new FormatException($"Format string '{format}' is not supported.")
+ };
+ }
+
+ ///
+ /// Formats the color as a CSS hsv() or hsva() string using degrees, percent saturation/value,
+ /// and fractional alpha.
+ ///
+ private string FormatHsvCss(bool includeAlpha = true)
+ {
+ int hDeg = (int)Math.Round(H);
+ int sPct = (int)Math.Round(S * 100.0);
+ int vPct = (int)Math.Round(V * 100.0);
+
+ if (includeAlpha)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "hsva({0}, {1}%, {2}%, {3:F2})",
+ hDeg,
+ sPct,
+ vPct,
+ A);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "hsv({0}, {1}%, {2}%)", hDeg, sPct, vPct);
+ }
+
+ ///
+ /// Formats the color as a CSS hsv() or hsva() string with all components as percentages.
+ ///
+ private string FormatHsvPercentCss(bool includeAlpha = true)
+ {
+ int hPct = (int)Math.Round(H / 360.0 * 100.0);
+ int sPct = (int)Math.Round(S * 100.0);
+ int vPct = (int)Math.Round(V * 100.0);
+
+ if (includeAlpha)
+ {
+ int aPct = (int)Math.Round(A * 100.0);
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "hsva({0}%, {1}%, {2}%, {3}%)",
+ hPct,
+ sPct,
+ vPct,
+ aPct);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "hsv({0}%, {1}%, {2}%)", hPct, sPct, vPct);
+ }
+
///
public override string ToString()
{
diff --git a/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs b/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
index 692ed09d08..047cf1c412 100644
--- a/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
@@ -1,4 +1,5 @@
using System;
+using System.Buffers;
using System.Collections.Generic;
using Avalonia.Media.TextFormatting.Unicode;
@@ -44,54 +45,7 @@ namespace Avalonia.Media.TextFormatting
var breakOportunities = new Queue();
- var currentPosition = textLine.FirstTextSourceIndex;
-
- // Note: trailing whitespace needs no special handling here. The LineBreakEnumerator does
- // not emit a non-required break inside trailing whitespace (LB07 forbids breaking before
- // a space, LB06 before a hard break), and the run-final break is excluded by
- // PositionWrap != textRun.Length below - so no break opportunity ever targets a glyph in
- // the trailing whitespace. Verified for ASCII and ideographic (U+3000) spaces by
- // Justify_Does_Not_Space_Trailing_Whitespace.
- for (var i = 0; i < lineImpl.TextRuns.Count; ++i)
- {
- var textRun = lineImpl.TextRuns[i];
- var text = textRun.Text;
-
- if (text.IsEmpty)
- {
- continue;
- }
-
- var lineBreakEnumerator = new LineBreakEnumerator(text.Span);
-
- while (lineBreakEnumerator.MoveNext(out var currentBreak))
- {
- if (!currentBreak.Required && currentBreak.PositionWrap != textRun.Length)
- {
- // The extra advance must land on the glyph that ENDS at the break
- // boundary (the last glyph before the break), so the widened gap sits on
- // the break itself. For whitespace breaks GetLineBreak has already pulled
- // PositionMeasure back onto the trailing whitespace glyph
- // (PositionMeasure < PositionWrap), so that position is the target as-is.
- // For zero-width breaks - CJK/Korean ideograph boundaries, hyphens and
- // other break-after punctuation - PositionMeasure == PositionWrap and
- // points one glyph PAST the boundary; step back one so we widen the gap the
- // break represents rather than the following gap. This also keeps the last
- // visible glyph of a CJK/Korean line unstretched: its only inbound break is
- // the run-final break, already excluded by PositionWrap != textRun.Length.
- var target = currentPosition + currentBreak.PositionMeasure;
-
- if (currentBreak.PositionMeasure == currentBreak.PositionWrap)
- {
- target -= 1;
- }
-
- breakOportunities.Enqueue(target);
- }
- }
-
- currentPosition += textRun.Length;
- }
+ CollectBreakOpportunities(lineImpl, breakOportunities);
if (breakOportunities.Count == 0)
{
@@ -107,7 +61,7 @@ namespace Avalonia.Media.TextFormatting
var remainingSpace = Math.Max(0, paragraphWidth - lineImpl.Width);
var spacing = remainingSpace / breakOportunities.Count;
- currentPosition = textLine.FirstTextSourceIndex;
+ var currentPosition = textLine.FirstTextSourceIndex;
for (var runIndex = 0; runIndex < lineImpl.TextRuns.Count; runIndex++)
{
@@ -166,5 +120,117 @@ namespace Avalonia.Media.TextFormatting
currentPosition += runLength;
}
}
+
+ ///
+ /// Collects the break opportunities of the line, in ascending text source position order.
+ ///
+ ///
+ ///
+ /// The opportunities are searched in the line's text rather than in each run's text: a run
+ /// boundary is not a text boundary - a font fallback or a style change splits a run in the
+ /// middle of a sentence - while the line breaker reports a break at the end of whatever text
+ /// it is given. Searching run by run therefore invents a break at every run boundary, and
+ /// filtering those artefacts out drops the real break whenever a word gap falls there.
+ ///
+ ///
+ /// Trailing whitespace needs no special handling. The LineBreakEnumerator does not emit a
+ /// non-required break inside trailing whitespace (LB07 forbids breaking before a space, LB06
+ /// before a hard break), and the final break is excluded below - so no break opportunity ever
+ /// targets a glyph in the trailing whitespace. Verified for ASCII and ideographic (U+3000)
+ /// spaces by Justify_Does_Not_Space_Trailing_Whitespace.
+ ///
+ ///
+ private static void CollectBreakOpportunities(TextLineImpl lineImpl, Queue breakOportunities)
+ {
+ var textRuns = lineImpl.TextRuns;
+ var currentPosition = lineImpl.FirstTextSourceIndex;
+ var runIndex = 0;
+
+ while (runIndex < textRuns.Count)
+ {
+ // Runs that carry no text (an embedded object, an end of line) interrupt the text, so
+ // each stretch of text runs between them is searched on its own.
+ var segmentStart = currentPosition;
+ var segmentLength = 0;
+ var segmentEnd = runIndex;
+
+ while (segmentEnd < textRuns.Count)
+ {
+ var textRun = textRuns[segmentEnd];
+
+ // A run whose length doesn't match its text can't be mapped back to text source
+ // positions by offset, so it ends the segment instead of shifting everything
+ // after it.
+ if (textRun.Text.IsEmpty || textRun.Text.Length != textRun.Length)
+ {
+ break;
+ }
+
+ segmentLength += textRun.Length;
+ ++segmentEnd;
+ }
+
+ if (segmentLength == 0)
+ {
+ currentPosition += textRuns[runIndex].Length;
+ ++runIndex;
+
+ continue;
+ }
+
+ var buffer = ArrayPool.Shared.Rent(segmentLength);
+
+ try
+ {
+ var offset = 0;
+
+ for (var i = runIndex; i < segmentEnd; i++)
+ {
+ var runText = textRuns[i].Text;
+
+ runText.Span.CopyTo(buffer.AsSpan(offset, runText.Length));
+
+ offset += runText.Length;
+ }
+
+ var lineBreakEnumerator = new LineBreakEnumerator(buffer.AsSpan(0, segmentLength));
+
+ while (lineBreakEnumerator.MoveNext(out var currentBreak))
+ {
+ if (currentBreak.Required || currentBreak.PositionWrap == segmentLength)
+ {
+ continue;
+ }
+
+ // The extra advance must land on the glyph that ENDS at the break boundary
+ // (the last glyph before the break), so the widened gap sits on the break
+ // itself. For whitespace breaks GetLineBreak has already pulled
+ // PositionMeasure back onto the trailing whitespace glyph
+ // (PositionMeasure < PositionWrap), so that position is the target as-is.
+ // For zero-width breaks - CJK/Korean ideograph boundaries, hyphens and other
+ // break-after punctuation - PositionMeasure == PositionWrap and points one
+ // glyph PAST the boundary; step back one so we widen the gap the break
+ // represents rather than the following gap. This also keeps the last visible
+ // glyph of a CJK/Korean line unstretched: its only inbound break is the
+ // segment-final one, already excluded above.
+ var target = segmentStart + currentBreak.PositionMeasure;
+
+ if (currentBreak.PositionMeasure == currentBreak.PositionWrap)
+ {
+ target -= 1;
+ }
+
+ breakOportunities.Enqueue(target);
+ }
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(buffer);
+ }
+
+ currentPosition = segmentStart + segmentLength;
+ runIndex = segmentEnd;
+ }
+ }
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs b/src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
index 0a9f2f1e86..cfeb290f2e 100644
--- a/src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
@@ -731,20 +731,27 @@ namespace Avalonia.Media.TextFormatting
splitGlyphIndex = ~foundIndex;
}
- // Visual leading = glyphs [0, splitGlyphIndex) → logically text[textLength..] (our "second")
- // Visual trailing = glyphs [splitGlyphIndex, end) → logically text[0..textLength] (our "first")
+ // Visual leading = glyphs [0, splitGlyphIndex) → logically the trailing text (our "second")
+ // Visual trailing = glyphs [splitGlyphIndex, end) → logically the leading text (our "first")
var secondGlyphs = _glyphInfos.Slice(sliceStart, splitGlyphIndex);
var firstGlyphs = _glyphInfos.Slice(sliceStart + splitGlyphIndex, glyphInfosLength - splitGlyphIndex);
- var firstText = Text.Slice(0, textLength);
- var secondText = Text.Slice(textLength);
+ // The glyph boundary sits past the requested offset when it falls inside a cluster,
+ // because the whole cluster stays with "first". The text boundary has to follow it so
+ // each half's text matches its glyphs - the ascending path snaps the same way.
+ var splitCharCount = splitGlyphIndex > 0
+ ? Math.Min(glyphInfos[splitGlyphIndex - 1].GlyphCluster - baseCluster, Text.Length)
+ : Text.Length;
+
+ var firstText = Text.Slice(0, splitCharCount);
+ var secondText = Text.Slice(splitCharCount);
// share the parent's cluster cache. The cache stores
// clusters in logical order, so "first" (text[0..textLength]) gets the
// leading slice and "second" gets the trailing slice — same indexing
// as the LTR case.
EnsureClusterCache();
- var firstClusterCount = FindClusterOffsetForSplit(textLength);
+ var firstClusterCount = FindClusterOffsetForSplit(splitCharCount);
var first = new ShapedBuffer(
firstText, firstGlyphs,
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs b/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
index b52b992746..94fdc5d3e3 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
@@ -294,9 +294,10 @@ namespace Avalonia.Media.TextFormatting
break;
}
- //Stop at the first cluster this typeface can't render
- if (!currentCodepoint.IsBreakChar &&
- currentCodepoint.GeneralCategory != GeneralCategory.Control &&
+ //Stop at the first cluster this typeface can't render. A cluster that only holds a
+ //default ignorable (a stray variation selector, say) renders nothing whichever font
+ //it lands on, so it never ends the run.
+ if (NeedsGlyph(currentCodepoint) &&
!ClusterIsCovered(clusterText, currentCodepoint, glyphTypeface, requireFullCluster))
{
break;
@@ -324,13 +325,25 @@ namespace Avalonia.Media.TextFormatting
return length > 0;
}
+ ///
+ /// Determines whether the codepoint is one a font is expected to provide a glyph for. Break
+ /// chars, control codepoints and default ignorables (variation selectors, joiners, ...) never
+ /// render - demanding a glyph for those would reject fonts that cover the cluster's actual
+ /// content. Format codepoints are not excluded wholesale: the invisible ones are all default
+ /// ignorable, while the rest (prepended concatenation marks like U+0600, interlinear
+ /// annotation chars) are visible and do need a glyph.
+ ///
+ private static bool NeedsGlyph(Codepoint codepoint)
+ => !codepoint.IsBreakChar
+ && codepoint.GeneralCategory != GeneralCategory.Control
+ && !codepoint.IsDefaultIgnorable;
+
///
/// Determines whether can render the first grapheme cluster in
/// . For a single-scalar cluster, or when
/// is false, only the base scalar is tested.
- /// Otherwise every scalar that needs a glyph (excluding break chars and control/format
- /// codepoints) must be present, so a base+mark cluster is only covered by a font that has the
- /// marks too.
+ /// Otherwise every scalar that needs a glyph must be present, so a base+mark cluster is only
+ /// covered by a font that has the marks too.
///
private static bool ClusterIsCovered(ReadOnlySpan clusterText, Codepoint firstCodepoint,
GlyphTypeface glyphTypeface, bool requireFullCluster)
@@ -346,7 +359,7 @@ namespace Avalonia.Media.TextFormatting
while (codepoints.MoveNext(out var codepoint))
{
- if (codepoint.IsBreakChar || codepoint.GeneralCategory is GeneralCategory.Control or GeneralCategory.Format)
+ if (!NeedsGlyph(codepoint))
{
continue;
}
@@ -380,7 +393,7 @@ namespace Avalonia.Media.TextFormatting
while (codepoints.MoveNext(out var codepoint))
{
- if (codepoint.IsBreakChar || codepoint.GeneralCategory is GeneralCategory.Control or GeneralCategory.Format)
+ if (!NeedsGlyph(codepoint))
{
continue;
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs b/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
index 4fe887dcbc..9810935c5a 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
@@ -634,7 +634,7 @@ namespace Avalonia.Media.TextFormatting
{
if (textLine.TextLineBreak is { IsSplit: true })
{
- textLines[textLines.Count - 1] = textLine.Collapse(GetCollapsingProperties(WidthIncludingTrailingWhitespace));
+ textLines[textLines.Count - 1] = textLine.Collapse(GetCollapsingProperties(textLine.WidthIncludingTrailingWhitespace));
}
break;
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
index 5be22121be..27bea36950 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
@@ -68,6 +68,33 @@ namespace Avalonia.Media.TextFormatting.Unicode
///
public EastAsianWidthClass EastAsianWidthClass => UnicodeData.GetEastAsianWidthClass(_value);
+ ///
+ /// Determines whether this has the Unicode Emoji property.
+ ///
+ ///
+ /// The property marks a codepoint that can be presented as emoji; it says nothing about which
+ /// presentation is the default. Use for that.
+ ///
+ public bool IsEmoji => UnicodeData.GetIsEmoji(_value);
+
+ ///
+ /// Determines whether this has the Unicode Emoji_Presentation
+ /// property, i.e. whether it defaults to an emoji presentation when no variation selector
+ /// follows it.
+ ///
+ public bool HasEmojiPresentation => UnicodeData.GetHasEmojiPresentation(_value);
+
+ ///
+ /// Determines whether this has the Unicode
+ /// Default_Ignorable_Code_Point property.
+ ///
+ ///
+ /// Default ignorable codepoints (variation selectors, joiners, the byte order mark, ...) are
+ /// meant to have no visible rendering of their own, so a font is not expected to provide a
+ /// glyph for them.
+ ///
+ public bool IsDefaultIgnorable => UnicodeData.GetIsDefaultIgnorable(_value);
+
///
/// Determines whether the codepoint's Unicode Script_Extensions property contains
/// .
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs
index 2d084b426f..9d3492a01e 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs
@@ -28,182 +28,182 @@ internal static class GraphemeBreakTrie
public static ReadOnlySpan Data =>
#endif
[
- 0x00000364, 0x0000036C, 0x00000374, 0x0000037C, 0x00000394, 0x0000039C, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374,
- 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374,
- 0x000003A4, 0x000003AC, 0x000003A8, 0x000003B0, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374,
- 0x000003B8, 0x000003C0, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x0000036C, 0x00000374, 0x000003C4, 0x000003CC, 0x000003D4, 0x000003DC,
- 0x000003E4, 0x000003EC, 0x000003F2, 0x000003FA, 0x0000036C, 0x00000374, 0x000003FF, 0x00000407, 0x0000040C, 0x00000414, 0x0000041A, 0x00000422,
- 0x00000421, 0x00000429, 0x0000042E, 0x00000436, 0x000004C6, 0x000004CD, 0x000004D1, 0x0000036C, 0x0000043E, 0x0000036C, 0x000004D8, 0x00000446,
- 0x000004E0, 0x000004E6, 0x000004EE, 0x000004F6, 0x000004FE, 0x00000504, 0x0000050C, 0x00000514, 0x0000051C, 0x0000051D, 0x00000525, 0x0000052A,
- 0x00000532, 0x00000538, 0x00000540, 0x00000548, 0x000004FE, 0x00000550, 0x00000558, 0x00000560, 0x00000568, 0x00000569, 0x00000571, 0x0000036C,
- 0x00000579, 0x0000057F, 0x00000587, 0x0000058F, 0x00000597, 0x00000598, 0x000005A0, 0x000005A8, 0x000005B0, 0x000005B6, 0x0000044E, 0x0000058F,
- 0x00000597, 0x0000036C, 0x000005BE, 0x0000094C, 0x0000036C, 0x000005C6, 0x000005CD, 0x0000036C, 0x0000036C, 0x000005D1, 0x000005D9, 0x0000036C,
- 0x000005DD, 0x000005E4, 0x0000036C, 0x000005EC, 0x000005F4, 0x000005FB, 0x00000567, 0x0000036C, 0x00000B5A, 0x00000603, 0x0000060B, 0x00000613,
- 0x0000061B, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000096F, 0x0000096F, 0x0000096F, 0x00000978, 0x00000978, 0x0000097E, 0x0000099D, 0x0000099D,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003C1, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000623, 0x00000629, 0x00000544, 0x00000544, 0x00000B5A, 0x00000631, 0x00000639, 0x0000036C,
- 0x0000049C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000641, 0x00000647, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000064F, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000656, 0x00000B5A, 0x0000065E, 0x00000666, 0x0000036C, 0x000003A0, 0x0000066E, 0x00000676,
- 0x0000067E, 0x00000683, 0x0000068B, 0x00000691, 0x00000699, 0x000006A1, 0x0000036C, 0x000006A9, 0x0000036C, 0x000006B0, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x000006B6, 0x000006BE, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003A4, 0x000003A4,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000004A2, 0x000004A8, 0x000006D6, 0x00000368, 0x0000036C, 0x0000036C, 0x000003A0, 0x000006C6,
- 0x0000036C, 0x000009B4, 0x0000036C, 0x0000036C, 0x000009BB, 0x000009C2, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000009C5, 0x000009CC, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000009D1, 0x000009D7,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000009DF, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x000009E5, 0x000009ED, 0x000009EF, 0x000009F7, 0x000009FF, 0x00000A07, 0x00000A0F, 0x00000A17, 0x00000A1F, 0x00000A27, 0x00000A2D,
- 0x00000A35, 0x00000A3C, 0x00000A43, 0x00000A4B, 0x00000A4E, 0x00000A56, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000A5E, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000A65, 0x0000036C, 0x00000A6D, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000006CB,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x000003ED, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003A4, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x000006D1, 0x0000036C, 0x0000036C, 0x000006D9, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000A73, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000006E0,
- 0x00000423, 0x0000036C, 0x0000036C, 0x000005DF, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x000006E8, 0x000006F0, 0x0000036C, 0x0000036C, 0x00000954, 0x00000957, 0x000006F8, 0x00000700, 0x0000036C, 0x00000708, 0x0000070F, 0x00000970,
- 0x00000717, 0x0000071B, 0x00000723, 0x0000072B, 0x0000036C, 0x00000733, 0x0000073B, 0x00000743, 0x0000036C, 0x0000074B, 0x00000410, 0x00000753,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000B5C, 0x0000075B, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9,
- 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7,
- 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC,
- 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA,
- 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8,
- 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6,
- 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB,
- 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9,
- 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7,
- 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC,
- 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA,
- 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8,
- 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6,
- 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB,
- 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9,
- 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7,
- 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC,
- 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA,
- 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8,
- 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6,
- 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB,
- 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9,
- 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7,
- 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC,
- 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA,
- 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8,
- 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6,
- 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB,
- 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9,
- 0x000009AA, 0x000009AB, 0x000009AC, 0x000009A6, 0x000009A7, 0x000009A8, 0x000009A9, 0x000009AA, 0x000009AB, 0x00000986, 0x0000098D, 0x0000099E,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000075F, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003B0, 0x000003B0, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000037C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000423, 0x0000036C, 0x0000036C, 0x000004B0, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000E10, 0x00000E10, 0x00000E50, 0x00000DB0, 0x00000DB0, 0x00000DB0, 0x00000DB0, 0x00000DB0,
- 0x00000DB0, 0x00000DB0, 0x00000DB0, 0x00000DB0, 0x00000E90, 0x00000EA0, 0x00000DB0, 0x00000DB0, 0x00000DB0, 0x00000DB0, 0x00000EE0, 0x00000DB0,
- 0x00000DB0, 0x00000DB0, 0x00000F10, 0x00000F50, 0x00000F90, 0x00000FC8, 0x00000DB0, 0x00000FFC, 0x00001030, 0x00001068, 0x00001084, 0x000010B8,
+ 0x00000364, 0x0000036C, 0x00000374, 0x0000037C, 0x00000394, 0x0000039C, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B,
+ 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B,
+ 0x000003A4, 0x000003AC, 0x000003B1, 0x000003B9, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B,
+ 0x000003C1, 0x000003C9, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x00000373, 0x0000037B, 0x000003CD, 0x000003D5, 0x000003DD, 0x000003E5,
+ 0x000003ED, 0x000003F5, 0x000003FB, 0x00000403, 0x00000373, 0x0000037B, 0x00000408, 0x00000410, 0x00000415, 0x0000041D, 0x00000423, 0x0000042B,
+ 0x0000042A, 0x00000432, 0x00000437, 0x0000043F, 0x000004E4, 0x000004EB, 0x000004EF, 0x00000373, 0x00000447, 0x00000373, 0x000004F6, 0x0000044F,
+ 0x000004FE, 0x00000504, 0x0000050C, 0x00000514, 0x0000051C, 0x00000522, 0x0000052A, 0x00000532, 0x0000053A, 0x0000053B, 0x00000543, 0x00000548,
+ 0x00000550, 0x00000556, 0x0000055E, 0x00000566, 0x0000051C, 0x0000056E, 0x00000576, 0x0000057E, 0x00000586, 0x00000587, 0x0000058F, 0x00000373,
+ 0x00000597, 0x0000059D, 0x000005A5, 0x000005AD, 0x000005B5, 0x000005B6, 0x000005BE, 0x000005C6, 0x000005CE, 0x000005D4, 0x00000457, 0x000005AD,
+ 0x000005B5, 0x00000373, 0x000005DC, 0x00000976, 0x00000373, 0x000005E4, 0x000005EB, 0x00000373, 0x00000373, 0x000005EF, 0x000005F7, 0x00000373,
+ 0x000005FB, 0x00000602, 0x00000373, 0x0000060A, 0x00000612, 0x00000619, 0x00000585, 0x00000373, 0x00000BFD, 0x00000621, 0x00000629, 0x00000631,
+ 0x00000639, 0x00000373, 0x00000373, 0x00000373, 0x00000999, 0x00000999, 0x0000099A, 0x000009AA, 0x000009AB, 0x000009B1, 0x000009D0, 0x000009D0,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000003CA, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000641, 0x00000647, 0x00000562, 0x00000562, 0x00000BFD, 0x0000064F, 0x00000657, 0x00000373,
+ 0x000004A5, 0x00000373, 0x00000373, 0x00000373, 0x0000065F, 0x00000665, 0x00000373, 0x00000373, 0x00000373, 0x0000066D, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000674, 0x00000BFD, 0x0000067C, 0x00000684, 0x00000373, 0x000003A0, 0x0000068C, 0x00000694,
+ 0x0000069C, 0x000006A1, 0x000006A9, 0x000006AF, 0x000006B7, 0x000006BF, 0x00000373, 0x000006C7, 0x00000373, 0x000006CE, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x000006D4, 0x000006DC, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000003A4, 0x000003A4,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000004AB, 0x000004B1, 0x000006F4, 0x000004B9, 0x00000373, 0x00000373, 0x000003A0, 0x000006E4,
+ 0x00000373, 0x000009E7, 0x00000373, 0x00000373, 0x000009EE, 0x000009F5, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000009F8, 0x000009FF, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000A04, 0x00000A0A,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000A12, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000A18, 0x00000A20, 0x00000A22, 0x00000A2A, 0x00000A32, 0x00000A3A, 0x00000A42, 0x00000A4A, 0x00000A52, 0x00000A5A, 0x00000A60,
+ 0x00000A68, 0x00000A6F, 0x00000A76, 0x00000A7E, 0x00000A81, 0x00000A89, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000A91, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000A98, 0x00000373, 0x00000AA0, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000006E9,
+ 0x00000373, 0x00000373, 0x00000373, 0x000003F6, 0x00000373, 0x00000373, 0x00000373, 0x000003A4, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x000006EF, 0x00000373, 0x00000373, 0x000006F7, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000BF4,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000AA6, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000006FE,
+ 0x0000042C, 0x00000373, 0x00000373, 0x000005FD, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000706, 0x0000070E, 0x00000373, 0x00000373, 0x0000097E, 0x00000981, 0x00000716, 0x0000071E, 0x00000373, 0x00000726, 0x0000072D, 0x000009A2,
+ 0x00000735, 0x00000739, 0x00000741, 0x00000749, 0x00000373, 0x00000751, 0x00000759, 0x00000761, 0x00000373, 0x00000769, 0x00000419, 0x00000771,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000BFF, 0x00000779, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC,
+ 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA,
+ 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF,
+ 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD,
+ 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB,
+ 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9,
+ 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE,
+ 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC,
+ 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA,
+ 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF,
+ 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD,
+ 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB,
+ 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9,
+ 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE,
+ 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC,
+ 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA,
+ 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF,
+ 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD,
+ 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB,
+ 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9,
+ 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE,
+ 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC,
+ 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA,
+ 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF,
+ 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD,
+ 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB,
+ 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9,
+ 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE,
+ 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC,
+ 0x000009DD, 0x000009DE, 0x000009DF, 0x000009D9, 0x000009DA, 0x000009DB, 0x000009DC, 0x000009DD, 0x000009DE, 0x000009B9, 0x000009C0, 0x000009D1,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x0000077D, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000785, 0x000003B9, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000004BD,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x0000042C, 0x00000BF5, 0x00000373, 0x000004C5, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000E10, 0x00000E10, 0x00000E50, 0x00000DCC, 0x00000DCC, 0x00000DCC, 0x00000DCC, 0x00000DCC,
+ 0x00000DCC, 0x00000DCC, 0x00000DCC, 0x00000DCC, 0x00000E90, 0x00000EC4, 0x00000DCC, 0x00000DCC, 0x00000DCC, 0x00000DCC, 0x00000F04, 0x00000DCC,
+ 0x00000DCC, 0x00000DCC, 0x00000F34, 0x00000F74, 0x00000FB4, 0x00000FEC, 0x00000DCC, 0x00001020, 0x00001054, 0x0000108C, 0x000010A8, 0x000010DC,
0x00000B44, 0x00000B74, 0x000009E2, 0x00000A21, 0x00000195, 0x00000195, 0x00000A5C, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195,
0x00000BB1, 0x00000BDA, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000A7F,
0x00000195, 0x00000C1A, 0x00000AB4, 0x00000C55, 0x00000C95, 0x00000CCF, 0x00000D0F, 0x00000D4F, 0x00000195, 0x00000195, 0x00000195, 0x00000195,
@@ -238,91 +238,91 @@ internal static class GraphemeBreakTrie
0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195,
0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195,
0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195,
- 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000AF4, 0x00000B04, 0x000007A2, 0x00000412,
- 0x0000041B, 0x000007A6, 0x000007AE, 0x00000454, 0x0000045C, 0x0000036C, 0x000007B6, 0x000007BD, 0x0000095F, 0x000007C3, 0x000007AE, 0x000007C8,
- 0x00000464, 0x0000036C, 0x0000036C, 0x000007D0, 0x00000410, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003ED, 0x000007D8, 0x000007E0, 0x000007E2,
- 0x000007EA, 0x000007F2, 0x00000B64, 0x000007FA, 0x0000046C, 0x00000802, 0x0000036C, 0x00000805, 0x0000080D, 0x0000036C, 0x0000036C, 0x00000815,
- 0x0000081D, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000822, 0x0000082A, 0x0000036C, 0x0000036C, 0x00000832,
- 0x0000042D, 0x0000036C, 0x0000036C, 0x0000083A, 0x0000036C, 0x0000036C, 0x00000840, 0x00000848, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000084D, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000B6B, 0x00000474, 0x0000047C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x00000854, 0x0000085C, 0x00000864, 0x00000868, 0x00000870, 0x00000B5A, 0x00000484, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000878, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000087D, 0x0000036C,
- 0x0000036C, 0x00000885, 0x0000088B, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000891, 0x0000048C, 0x0000036C, 0x00000899, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000089F, 0x00000494, 0x000008A7, 0x000008AF,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000390, 0x000008B7, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000008E1,
- 0x0000036B, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x000004B7, 0x000008F1, 0x00000625, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000008F9, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000394, 0x000003A4, 0x000003A4, 0x000003A4,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x000003A4, 0x000003A4, 0x000003A4, 0x000003A4, 0x000003A4, 0x000003A4, 0x000003A4, 0x000004BE,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x00000394,
- 0x00000394, 0x00000394, 0x00000394, 0x00000394, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000767, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000042D, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000076F, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000777, 0x0000077E, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x00000641, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000786, 0x0000036C, 0x0000078C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000792, 0x0000036C, 0x00000424,
- 0x0000036C, 0x0000036C, 0x00000429, 0x0000036C, 0x0000079A, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x00000423, 0x000008BF, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000008C3, 0x0000036C, 0x000008C9,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000995, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000008CF, 0x00000967, 0x000008D5, 0x0000036C,
- 0x0000036C, 0x000008DC, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003A4, 0x000008E9,
- 0x0000041B, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000003A4, 0x00000901, 0x000003A4, 0x00000908, 0x0000090F, 0x00000917, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000091F, 0x00000927, 0x0000036C, 0x0000036C, 0x000007C4, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x000008C9, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x00000565, 0x0000036C, 0x0000092C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000092C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000545, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x00000934, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000008C9, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x000005DA, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x000009EC, 0x00000A7A, 0x0000036C, 0x0000036C, 0x00000A7E,
- 0x00000A68, 0x00000A86, 0x00000A8B, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000A93, 0x00000A9B, 0x00000AA2, 0x00000AA6, 0x00000944, 0x00000AAE,
- 0x00000AB5, 0x00000ABD, 0x00000AA4, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AC5, 0x00000AA6, 0x00000AA6, 0x00000AC8,
- 0x00000AA6, 0x00000AA6, 0x0000093C, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AD0, 0x00000AA6,
- 0x00000AD8, 0x00000AE0, 0x00000AE6, 0x00000AED, 0x00000AF4, 0x00000AFC, 0x00000B04, 0x00000AA6, 0x00000AA6, 0x00000B0B, 0x0000036C, 0x00000AA6,
- 0x00000AA6, 0x00000B13, 0x00000B1A, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000B22, 0x00000AA6, 0x00000A7A,
- 0x0000036C, 0x00000B2A, 0x0000036C, 0x00000B32, 0x00000B37, 0x00000B3F, 0x00000AA6, 0x00000B47, 0x00000B4A, 0x00000AD6, 0x00000AA6, 0x00000AA6,
- 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x0000036C, 0x0000036C, 0x00000B52, 0x00000AA2, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x0000036C,
- 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x0000036C, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6,
- 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6,
- 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6, 0x00000AA6,
- 0x00000AA6, 0x00000AA6, 0x00000AD8, 0x00010363, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
+ 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000195, 0x00000AF4, 0x00000B04, 0x000007C4, 0x0000041B,
+ 0x00000424, 0x000007C8, 0x000007D0, 0x0000045D, 0x00000465, 0x00000373, 0x000007D8, 0x000007DF, 0x00000989, 0x000007E5, 0x000007D0, 0x000007EA,
+ 0x0000046D, 0x00000373, 0x00000373, 0x000007F2, 0x00000419, 0x00000373, 0x00000373, 0x00000373, 0x000003F6, 0x000007FA, 0x00000802, 0x00000804,
+ 0x0000080C, 0x00000814, 0x00000C07, 0x0000081C, 0x00000475, 0x00000824, 0x00000373, 0x00000827, 0x0000082F, 0x00000373, 0x00000373, 0x00000837,
+ 0x0000083F, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000844, 0x0000084C, 0x00000373, 0x00000373, 0x00000854,
+ 0x00000436, 0x00000373, 0x00000373, 0x0000085C, 0x00000373, 0x00000373, 0x00000862, 0x0000086A, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x0000086F, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000C0E, 0x0000047D, 0x00000485,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000876, 0x0000087E, 0x00000886, 0x0000088A, 0x00000892, 0x00000BFD, 0x0000048D, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x0000089A, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x0000089F, 0x00000373,
+ 0x00000373, 0x000008A7, 0x000008AD, 0x00000373, 0x00000373, 0x00000373, 0x000008B3, 0x00000495, 0x00000373, 0x000008BB, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000008C1, 0x0000049D, 0x000008C9, 0x000008D1,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000390, 0x000008D9, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000903,
+ 0x000004BC, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x000004CC, 0x00000913, 0x00000643, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x0000091B, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000004D4, 0x00000966, 0x00000966, 0x00000966,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x00000966, 0x00000966, 0x00000966, 0x00000966, 0x00000966, 0x00000966, 0x00000966, 0x000004DC,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4,
+ 0x000004D4, 0x000004D4, 0x000004D4, 0x000004D4, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000789, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000436, 0x00000373, 0x00000373, 0x00000373, 0x00000791, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000799, 0x000007A0, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x0000065F, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000007A8, 0x00000373, 0x000007AE,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000007B4, 0x00000373, 0x0000042D,
+ 0x00000373, 0x00000373, 0x00000432, 0x00000373, 0x000007BC, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x0000042C, 0x000008E1, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000008E5, 0x00000373, 0x000008EB,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000009C8, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000008F1, 0x00000991, 0x000008F7, 0x00000373,
+ 0x00000373, 0x000008FE, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000003A4, 0x0000090B,
+ 0x00000424, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000003A4, 0x00000923, 0x000003A4, 0x0000092A, 0x00000931, 0x00000939, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000941, 0x00000949, 0x00000373, 0x00000373, 0x000007E6, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x000008EB, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000583, 0x00000373, 0x0000094E, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x0000094E, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000563, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000956, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x000008EB, 0x00000373, 0x00000373,
+ 0x00000373, 0x000005F8, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000AAD, 0x00000AB2, 0x00000373, 0x00000373, 0x00000AB6,
+ 0x00000ABE, 0x00000AC6, 0x00000ACB, 0x00000373, 0x00000373, 0x00000373, 0x00000AD3, 0x00000ADB, 0x00000AE2, 0x00000AE6, 0x0000096E, 0x00000AEE,
+ 0x00000AF5, 0x00000AFD, 0x00000AE4, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000B05, 0x00000B0D, 0x00000B05, 0x00000B13, 0x00000B1B,
+ 0x00000B05, 0x00000B23, 0x0000095E, 0x00000B05, 0x00000B2B, 0x00000B33, 0x00000B05, 0x00000B05, 0x00000B05, 0x00000B05, 0x00000B34, 0x00000B05,
+ 0x00000B3C, 0x00000B44, 0x00000B4A, 0x00000B51, 0x00000B58, 0x00000B60, 0x00000B68, 0x00000B05, 0x00000B05, 0x00000B6F, 0x00000373, 0x00000B05,
+ 0x00000B05, 0x00000B77, 0x00000B7F, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000B87, 0x00000B8F, 0x00000AB2,
+ 0x00000373, 0x00000B97, 0x00000373, 0x00000B9F, 0x00000BA4, 0x00000BAC, 0x00000AE6, 0x00000BB4, 0x00000BB7, 0x00000BBE, 0x00000B05, 0x00000B05,
+ 0x00000B05, 0x00000B05, 0x00000B05, 0x00000373, 0x00000373, 0x00000BC6, 0x00000BCE, 0x00000BD6, 0x00000B05, 0x00000BDD, 0x00000BE5, 0x00000373,
+ 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000373, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6,
+ 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6,
+ 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6, 0x00000AE6,
+ 0x00000AE6, 0x00000AE6, 0x00000BEC, 0x00010363, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
0x00000001, 0x00000001, 0x00000009, 0x00000001, 0x00000001, 0x00000002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080,
+ 0x00000080, 0x00000080, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -336,14 +336,17 @@ internal static class GraphemeBreakTrie
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
- 0x00000000, 0x00000001, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000201, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000266, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -362,7 +365,7 @@ internal static class GraphemeBreakTrie
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0000000C, 0x0000000C, 0x0000000C, 0x0000000C, 0x0000000C, 0x0000000C, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000201, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
@@ -422,20 +425,27 @@ internal static class GraphemeBreakTrie
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000001, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000266, 0x00000266, 0x00000266, 0x00000201, 0x00000266, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000006, 0x00000071, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000201, 0x00000206, 0x00000271, 0x00000201, 0x00000201, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001, 0x00000001, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000201,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201,
+ 0x00000201, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000201,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000266, 0x00000266, 0x00000266, 0x00000266,
+ 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000201,
+ 0x00000201, 0x00000201, 0x00000201, 0x00000201, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000,
@@ -558,7 +568,7 @@ internal static class GraphemeBreakTrie
0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E,
+ 0x00000266, 0x00000266, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E,
0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000026, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -611,8 +621,8 @@ internal static class GraphemeBreakTrie
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
@@ -659,169 +669,173 @@ internal static class GraphemeBreakTrie
0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x00000000, 0x0000000E, 0x00000066, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000266, 0x00000266, 0x00000266, 0x00000266,
+ 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040,
- 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000026,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000026, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
- 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x00000066, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x00000066, 0x0000000E, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000026,
- 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066,
- 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
- 0x00000066, 0x00000000, 0x00000066, 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x0000000E,
- 0x0000000E, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000026, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E,
+ 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x0000000E,
- 0x0000000E, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000,
- 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x0000000E,
+ 0x0000000E, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x00000066, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000,
+ 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x0000000E, 0x00000066,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
- 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
- 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x0000000E, 0x00000066,
+ 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000040,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000026, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E,
- 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000066, 0x0000000E, 0x00000066, 0x00000066,
- 0x00000066, 0x0000000E, 0x00000066, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E,
+ 0x0000000E, 0x00000066, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x0000000E, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x0000000E, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
- 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000000,
- 0x00000066, 0x00000066, 0x00000000, 0x0000000E, 0x0000000E, 0x00000066, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E,
- 0x00000066, 0x00000066, 0x00000026, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000000, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000026,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000066, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x00000066, 0x00000066,
+ 0x0000000E, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E,
+ 0x0000000E, 0x0000000E, 0x0000000E, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x0000000E, 0x0000000E, 0x00000066, 0x0000000E, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000000, 0x00000000, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000026, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
- 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E,
- 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000066, 0x00000066, 0x00000066,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
- 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E,
+ 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
- 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000066, 0x00000066,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000066, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D,
- 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D,
- 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000066, 0x00000066, 0x00000066, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000066,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000066, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000092,
+ 0x00000192, 0x00000092, 0x00000000, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x000001E6, 0x000001E6, 0x000001E6, 0x000001E6, 0x000001E6,
+ 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266,
+ 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266,
+ 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000266, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D,
+ 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D,
+ 0x0000018D, 0x0000018D, 0x0000018D, 0x0000018D, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000E, 0x0000000E,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0000000E, 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -835,7 +849,10 @@ internal static class GraphemeBreakTrie
0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E, 0x0000000E,
0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008,
0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008,
- 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000208,
+ 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008,
+ 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008,
+ 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000210, 0x00000010, 0x00000010, 0x00000010,
0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010,
0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010,
0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x0000000F, 0x0000000F, 0x0000000F, 0x0000000F,
@@ -856,155 +873,192 @@ internal static class GraphemeBreakTrie
0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000A, 0x0000000B, 0x0000000B, 0x0000000B,
0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B,
0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B, 0x0000000B,
- 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000092, 0x00000092, 0x00000092,
+ 0x00000192, 0x00000092, 0x00000092, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000000, 0x00000012,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092,
+ 0x00000092, 0x00000192, 0x00000192, 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000,
+ 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000092, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000192,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000192, 0x00000092, 0x00000092, 0x00000092, 0x00000092,
+ 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000192, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000092, 0x00000000, 0x00000092, 0x00000000, 0x00000092,
+ 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000092, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000192, 0x00000192,
+ 0x00000092, 0x00000192, 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000192, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000192, 0x00000192,
+ 0x00000092, 0x00000092, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000192, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
+ 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
- 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000000,
- 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000,
- 0x00000000, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000192, 0x00000092, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000092,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000192, 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092,
+ 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000092, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000092, 0x00000092, 0x00000092,
+ 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000092, 0x00000192, 0x00000092, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000092, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000092, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000092,
+ 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000092,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000092,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000192, 0x00000092, 0x00000092, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000000,
+ 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000000, 0x00000000, 0x00000000, 0x00000092, 0x00000000, 0x00000192,
+ 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000092, 0x00000000, 0x00000000, 0x00000092, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000192, 0x00000012, 0x00000012, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012,
+ 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012, 0x00000012, 0x00000192,
+ 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192, 0x00000192,
+ 0x00000192, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000012, 0x00000012, 0x00000012, 0x00000012,
+ 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000040,
- 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000,
- 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000000, 0x00000040, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000000, 0x00000040, 0x00000040, 0x00000040, 0x00000040,
+ 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000
];
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.Lookups.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.Lookups.cs
index 7ba153935d..8d5349d311 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.Lookups.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.Lookups.cs
@@ -104,6 +104,37 @@ namespace Avalonia.Media.TextFormatting.Unicode
return (IndicConjunctBreakClass)((GraphemeBreakTrie.Trie.Get(codepoint) >> INDICCONJUNCTBREAK_SHIFT) & INDICCONJUNCTBREAK_MASK);
}
+ ///
+ /// Gets whether the codepoint has the Unicode Emoji property.
+ ///
+ /// The codepoint in question.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool GetIsEmoji(uint codepoint)
+ {
+ return (GraphemeBreakTrie.Trie.Get(codepoint) & EMOJI_FLAG) != 0;
+ }
+
+ ///
+ /// Gets whether the codepoint has the Unicode Emoji_Presentation property, i.e. whether
+ /// it defaults to an emoji presentation when no variation selector is present.
+ ///
+ /// The codepoint in question.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool GetHasEmojiPresentation(uint codepoint)
+ {
+ return (GraphemeBreakTrie.Trie.Get(codepoint) & EMOJIPRESENTATION_FLAG) != 0;
+ }
+
+ ///
+ /// Gets whether the codepoint has the Unicode Default_Ignorable_Code_Point property.
+ ///
+ /// The codepoint in question.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool GetIsDefaultIgnorable(uint codepoint)
+ {
+ return (GraphemeBreakTrie.Trie.Get(codepoint) & DEFAULTIGNORABLE_FLAG) != 0;
+ }
+
///
/// Gets the EastAsianWidth class for the Unicode codepoint.
///
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs
index 5d6ab135aa..540b0208d2 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs
@@ -30,6 +30,17 @@ namespace Avalonia.Media.TextFormatting.Unicode
internal const int BIDIPAIREDBRACKEDTYPE_SHIFT = BIDIPAIREDBRACKED_BITS;
internal const int BIDICLASS_SHIFT = BIDIPAIREDBRACKED_BITS + BIDIPAIREDBRACKEDTYPE_BITS;
+ // Single-bit properties packed into the spare bits of the GraphemeBreak trie word, which
+ // otherwise only uses GRAPHEMEBREAK_BITS + INDICCONJUNCTBREAK_BITS. Emoji and
+ // Emoji_Presentation come from the same emoji-data.txt the grapheme break data is read from.
+ internal const int EMOJI_SHIFT = INDICCONJUNCTBREAK_SHIFT + INDICCONJUNCTBREAK_BITS;
+ internal const int EMOJIPRESENTATION_SHIFT = EMOJI_SHIFT + 1;
+ internal const int DEFAULTIGNORABLE_SHIFT = EMOJIPRESENTATION_SHIFT + 1;
+
+ internal const uint EMOJI_FLAG = 1u << EMOJI_SHIFT;
+ internal const uint EMOJIPRESENTATION_FLAG = 1u << EMOJIPRESENTATION_SHIFT;
+ internal const uint DEFAULTIGNORABLE_FLAG = 1u << DEFAULTIGNORABLE_SHIFT;
+
internal const int CATEGORY_MASK = (1 << CATEGORY_BITS) - 1;
internal const int SCRIPT_MASK = (1 << SCRIPT_BITS) - 1;
internal const int LINEBREAK_MASK = (1 << LINEBREAK_BITS) - 1;
diff --git a/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs b/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs
index cce11db12d..cd8f1f3f21 100644
--- a/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs
+++ b/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Media;
@@ -41,6 +42,9 @@ namespace Avalonia.Platform
public PlatformHotkeyConfiguration HotkeyConfiguration =>
AvaloniaLocator.Current.GetRequiredService();
+ public virtual string PreferredApplicationLanguage =>
+ CultureInfo.InstalledUICulture.Name;
+
public virtual PlatformColorValues GetColorValues()
{
return new PlatformColorValues
@@ -50,11 +54,18 @@ namespace Avalonia.Platform
}
public virtual event EventHandler? ColorValuesChanged;
+ public virtual event EventHandler? PreferredApplicationLanguageChanged;
protected void OnColorValuesChanged(PlatformColorValues colorValues)
{
Dispatcher.UIThread.Send(
_ => ColorValuesChanged?.Invoke(this, colorValues));
}
+
+ protected void OnPreferredApplicationLanguageChanged()
+ {
+ Dispatcher.UIThread.Send(
+ _ => PreferredApplicationLanguageChanged?.Invoke(this, EventArgs.Empty));
+ }
}
}
diff --git a/src/Avalonia.Base/Platform/IGeometryContext.cs b/src/Avalonia.Base/Platform/IGeometryContext.cs
index 4305dccd3f..c112ae63d4 100644
--- a/src/Avalonia.Base/Platform/IGeometryContext.cs
+++ b/src/Avalonia.Base/Platform/IGeometryContext.cs
@@ -11,14 +11,19 @@ namespace Avalonia.Platform
///
/// Draws an arc to the specified point.
///
- /// The destination point.
- /// The radii of an oval whose perimeter is used to draw the angle.
- /// The rotation angle (in radians) of the oval that specifies the curve.
- /// true to draw the arc greater than 180 degrees; otherwise, false.
+ /// The destination point where the arc ends.
+ /// The radii of an ellipse whose path is used to draw the arc.
+ ///
+ /// The rotation angle (in degrees) of the ellipse that specifies the path of the arc; positive values are clockwise.
+ /// This will rotate the entire arc relative to the X-axis and is not commonly used.
+ ///
+ ///
+ /// Specifies whether the arc should follow the longer path around an ellipse rather than the shorter one.
+ /// true to draw the arc greater than 180 degrees; otherwise, false.
///
/// A value that indicates whether the arc is drawn in the Clockwise or Counterclockwise direction.
///
- /// Whether the segment is stroked
+ /// Whether the segment is stroked.
void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection, bool isStroked = true);
///
@@ -34,22 +39,22 @@ namespace Avalonia.Platform
/// The first control point used to specify the shape of the curve.
/// The second control point used to specify the shape of the curve.
/// The destination point for the end of the curve.
- /// Whether the segment is stroked
+ /// Whether the segment is stroked.
void CubicBezierTo(Point controlPoint1, Point controlPoint2, Point endPoint, bool isStroked = true);
///
- /// Draws a quadratic Bezier curve to the specified point
+ /// Draws a quadratic Bezier curve to the specified point.
///
/// The control point used to specify the shape of the curve.
/// The destination point for the end of the curve.
- /// Whether the segment is stroked
+ /// Whether the segment is stroked.
void QuadraticBezierTo(Point controlPoint, Point endPoint, bool isStroked = true);
///
/// Draws a line to the specified point.
///
/// The destination point.
- /// Whether the segment is stroked
+ /// Whether the segment is stroked.
void LineTo(Point point, bool isStroked = true);
///
diff --git a/src/Avalonia.Base/Platform/IPlatformSettings.cs b/src/Avalonia.Base/Platform/IPlatformSettings.cs
index 46980c6d51..a45d8dc20f 100644
--- a/src/Avalonia.Base/Platform/IPlatformSettings.cs
+++ b/src/Avalonia.Base/Platform/IPlatformSettings.cs
@@ -37,12 +37,26 @@ namespace Avalonia.Platform
/// Holding duration between pointer press and when event is fired.
///
TimeSpan HoldWaitDuration { get; }
-
+
///
/// Get a configuration for platform-specific hotkeys in an Avalonia application.
///
PlatformHotkeyConfiguration HotkeyConfiguration { get; }
-
+
+ ///
+ /// Gets the preferred application language as specified in the operating system settings.
+ ///
+ ///
+ /// BCP 47 language tag. Examples: en, en-US or zh-Hans-CN.
+ /// Can be empty if the operating system doesn't report a preferred language.
+ ///
+ ///
+ /// Most platforms read this value from the operating system instead of the .NET runtime,
+ /// so a language tag can be returned even in globalization-invariant mode.
+ /// When that mode is disabled, the tag can be passed to .
+ ///
+ string PreferredApplicationLanguage { get; }
+
///
/// Gets current system color values including dark mode and accent colors.
///
@@ -52,5 +66,10 @@ namespace Avalonia.Platform
/// Raises when current system color values are changed. Including changing of a dark mode and accent colors.
///
event EventHandler? ColorValuesChanged;
+
+ ///
+ /// Raises when the preferred application language is changed in the operating system settings.
+ ///
+ event EventHandler? PreferredApplicationLanguageChanged;
}
}
diff --git a/src/Avalonia.Base/Platform/Storage/FileIO/StorageBookmarkHelper.cs b/src/Avalonia.Base/Platform/Storage/FileIO/StorageBookmarkHelper.cs
index 4c43331803..cafbfdfa25 100644
--- a/src/Avalonia.Base/Platform/Storage/FileIO/StorageBookmarkHelper.cs
+++ b/src/Avalonia.Base/Platform/Storage/FileIO/StorageBookmarkHelper.cs
@@ -86,20 +86,19 @@ internal static class StorageBookmarkHelper
Span decodedBookmark;
- // Each base64 character represents 6 bits, but to be safe,
- var arrayPool = ArrayPool.Shared.Rent(HeaderLength + base64bookmark.Length * 6);
- if (Convert.TryFromBase64Chars(base64bookmark, arrayPool, out int bytesWritten))
- {
- decodedBookmark = arrayPool.AsSpan().Slice(0, bytesWritten);
- }
- else
- {
- nativeBookmark = null;
- return DecodeResult.InvalidFormat;
- }
+ var arrayPool = ArrayPool.Shared.Rent(HeaderLength + base64bookmark.Length / 4 * 3);
try
{
+ // Each base64 character represents 6 bits, but to be safe,
+ if (!Convert.TryFromBase64Chars(base64bookmark, arrayPool, out int bytesWritten))
+ {
+ nativeBookmark = null;
+ return DecodeResult.InvalidFormat;
+ }
+
+ decodedBookmark = arrayPool.AsSpan(..bytesWritten);
+
if (decodedBookmark.Length < HeaderLength
// Check if decoded string starts with the correct prefix, checking v1 at the same time.
&& !AvaHeaderPrefix.SequenceEqual(decodedBookmark.Slice(0, AvaHeaderPrefix.Length)))
diff --git a/src/Avalonia.Base/Rendering/Composition/Animations/Interpolators.cs b/src/Avalonia.Base/Rendering/Composition/Animations/Interpolators.cs
index f801bd1c66..47e1972a12 100644
--- a/src/Avalonia.Base/Rendering/Composition/Animations/Interpolators.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Animations/Interpolators.cs
@@ -77,7 +77,7 @@ namespace Avalonia.Rendering.Composition.Animations
class ColorInterpolator : IInterpolator
{
- static byte Lerp(float a, float b, float p) => (byte) Math.Max(0, Math.Min(255, (p * (b - a) + a)));
+ static byte Lerp(float a, float b, float p) => (byte)Math.Clamp(float.Lerp(a, b, p), 0, 255);
public static Avalonia.Media.Color
LerpRGB(Avalonia.Media.Color to, Avalonia.Media.Color from, float progress) =>
diff --git a/src/Avalonia.Base/Rendering/Composition/Expressions/BuiltInExpressionFfi.cs b/src/Avalonia.Base/Rendering/Composition/Expressions/BuiltInExpressionFfi.cs
index 4f6ac03971..a3ee451f80 100644
--- a/src/Avalonia.Base/Rendering/Composition/Expressions/BuiltInExpressionFfi.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Expressions/BuiltInExpressionFfi.cs
@@ -13,8 +13,8 @@ namespace Avalonia.Rendering.Composition.Expressions
{
private readonly DelegateExpressionFfi _registry;
- static float Lerp(float a, float b, float p) => p * (b - a) + a;
- static double Lerp(double a, double b, double p) => p * (b - a) + a;
+ static float Lerp(float a, float b, float p) => float.Lerp(a, b, p);
+ static double Lerp(double a, double b, double p) => double.Lerp(a, b, p);
static Matrix3x2 Inverse(Matrix3x2 m)
{
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawingSurface.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawingSurface.cs
index 04350902a6..7430be040b 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawingSurface.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawingSurface.cs
@@ -9,6 +9,7 @@ internal class ServerCompositionDrawingSurface : ServerCompositionSurface, IDisp
{
private IRef? _bitmap;
private IPlatformRenderInterfaceContext? _createdWithContext;
+ private bool _disposed;
public override IRef? Bitmap
{
get
@@ -41,6 +42,17 @@ internal class ServerCompositionDrawingSurface : ServerCompositionSurface, IDisp
void Update(IBitmapImpl newImage, IPlatformRenderInterfaceContext context)
{
+ if (_disposed)
+ {
+ // Batches are processed with disposals before server jobs, so an update job
+ // can be processed after this surface was disposed in the same batch.
+ // Dispose the snapshot here on the render thread (context is current)
+ // instead of orphaning it: an orphaned ref is only ever released by the
+ // Ref critical finalizer, which then performs GPU work on the finalizer
+ // thread and races the render loop (#21865).
+ newImage.Dispose();
+ return;
+ }
_bitmap?.Dispose();
_bitmap = RefCountable.Create(newImage);
_createdWithContext = context;
@@ -92,5 +104,7 @@ internal class ServerCompositionDrawingSurface : ServerCompositionSurface, IDisp
public void Dispose()
{
_bitmap?.Dispose();
+ _bitmap = null;
+ _disposed = true;
}
}
diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs
index 16feb0e803..80d8689772 100644
--- a/src/Avalonia.Base/StyledElement.cs
+++ b/src/Avalonia.Base/StyledElement.cs
@@ -612,13 +612,6 @@ namespace Avalonia
{
OnControlThemeChanged();
}
- else if (change.Property == ThemeVariant.RequestedThemeVariantProperty)
- {
- if (change.GetNewValue() is {} themeVariant && themeVariant != ThemeVariant.Default)
- SetValue(ThemeVariant.ActualThemeVariantProperty, themeVariant);
- else
- ClearValue(ThemeVariant.ActualThemeVariantProperty);
- }
else if (change.Property == ThemeVariant.ActualThemeVariantProperty)
{
ActualThemeVariantChanged?.Invoke(this, EventArgs.Empty);
diff --git a/src/Avalonia.Base/Styling/IThemeVariantRoot.cs b/src/Avalonia.Base/Styling/IThemeVariantRoot.cs
new file mode 100644
index 0000000000..c16f93f1ac
--- /dev/null
+++ b/src/Avalonia.Base/Styling/IThemeVariantRoot.cs
@@ -0,0 +1,12 @@
+namespace Avalonia.Styling;
+
+///
+/// Implemented by objects which resolve a requested theme variant from the platform.
+///
+internal interface IThemeVariantRoot
+{
+ ///
+ /// Gets whether this object currently acts as a theme variant root (it has no parent).
+ ///
+ bool IsThemeVariantRoot { get; }
+}
diff --git a/src/Avalonia.Base/Styling/ThemeVariant.cs b/src/Avalonia.Base/Styling/ThemeVariant.cs
index b469ea5b28..7af270a3a1 100644
--- a/src/Avalonia.Base/Styling/ThemeVariant.cs
+++ b/src/Avalonia.Base/Styling/ThemeVariant.cs
@@ -1,6 +1,6 @@
using System;
using System.ComponentModel;
-using System.Text;
+using Avalonia.Logging;
using Avalonia.Platform;
namespace Avalonia.Styling;
@@ -45,7 +45,12 @@ public sealed record ThemeVariant
internal static readonly StyledProperty RequestedThemeVariantProperty =
AvaloniaProperty.Register(
"RequestedThemeVariant", defaultValue: Default);
-
+
+ static ThemeVariant()
+ {
+ RequestedThemeVariantProperty.Changed.AddClassHandler((x, _) => UpdateActualThemeVariant(x));
+ }
+
///
/// Creates a new instance of the
///
@@ -79,6 +84,42 @@ public sealed record ThemeVariant
///
public ThemeVariant? InheritVariant { get; }
+ internal static void UpdateActualThemeVariant(AvaloniaObject target)
+ {
+ var requested = target.GetValue(RequestedThemeVariantProperty) ?? Default;
+
+ if (requested != Default)
+ {
+ target.SetValue(ActualThemeVariantProperty, requested);
+ return;
+ }
+
+ if (target is IThemeVariantRoot { IsThemeVariantRoot: true })
+ {
+ var actual = GetPlatformThemeVariant();
+
+ Logger.TryGet(LogEventLevel.Debug, LogArea.Platform)
+ ?.Log(target, "Requested Default theme variant, used {ActualThemeVariant} platform variant", actual);
+
+ target.SetValue(ActualThemeVariantProperty, actual);
+ }
+ else
+ {
+ Logger.TryGet(LogEventLevel.Debug, LogArea.Platform)
+ ?.Log(target, "Requested Default theme variant, inheriting from parent");
+
+ target.ClearValue(ActualThemeVariantProperty);
+ }
+ }
+
+ private static ThemeVariant GetPlatformThemeVariant()
+ {
+ var variant = AvaloniaLocator.Current.GetService()?.GetColorValues().ThemeVariant ??
+ PlatformThemeVariant.Light;
+
+ return (ThemeVariant)variant;
+ }
+
public override string ToString()
{
return Key.ToString() ?? $"ThemeVariant {{ Key = {Key} }}";
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index acf90179b1..d11fd08343 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -157,6 +157,12 @@ namespace Avalonia.Build.Tasks
var arg1 = new CustomAttributeArgument(strType, "AvaloniaUseCompiledBindingsByDefault");
var arg2 = new CustomAttributeArgument(strType, defaultCompileBindings.ToString());
asm.CustomAttributes.Add(new CustomAttribute(ctor) { ConstructorArguments = { arg1, arg2 } });
+ if (createSourceInfo)
+ {
+ var arg3 = new CustomAttributeArgument(strType, "AvaloniaXamlCreateSourceInfo");
+ var arg4 = new CustomAttributeArgument(strType, createSourceInfo.ToString());
+ asm.CustomAttributes.Add(new CustomAttribute(ctor) { ConstructorArguments = { arg3, arg4 } });
+ }
}
TypeDefinition AddClass(string name, TypeAttributes extraAttributes = 0)
diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs
index 0b1e20c395..769ab39377 100644
--- a/src/Avalonia.Controls/Application.cs
+++ b/src/Avalonia.Controls/Application.cs
@@ -30,7 +30,7 @@ namespace Avalonia
/// method.
/// - Tracks the lifetime of the application.
///
- public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IResourceHost, IOptionalFeatureProvider
+ public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IThemeVariantRoot, IResourceHost, IOptionalFeatureProvider
{
///
/// The application-global data templates.
@@ -97,6 +97,8 @@ namespace Avalonia
[System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1030", Justification = "False positive.")]
public ThemeVariant ActualThemeVariant => GetValue(ActualThemeVariantProperty);
+ bool IThemeVariantRoot.IsThemeVariantRoot => true;
+
///
/// Gets the current instance of the class.
///
@@ -250,11 +252,7 @@ namespace Avalonia
AvaloniaSynchronizationContext.InstallIfNeeded();
InputManager = new InputManager();
- if (PlatformSettings is { } settings)
- {
- settings.ColorValuesChanged += OnColorValuesChanged;
- OnColorValuesChanged(settings, settings.GetColorValues());
- }
+ InitializeThemeVariant();
AvaloniaLocator.CurrentMutable
.Bind().ToTransient()
@@ -328,21 +326,7 @@ namespace Avalonia
{
base.OnPropertyChanged(change);
- if (change.Property == RequestedThemeVariantProperty)
- {
- if (change.GetNewValue() is { } themeVariant)
- {
- if (themeVariant == ThemeVariant.Default)
- {
- ClearValue(ActualThemeVariantProperty);
- }
- else
- {
- SetValue(ActualThemeVariantProperty, themeVariant);
- }
- }
- }
- else if (change.Property == ActualThemeVariantProperty)
+ if (change.Property == ActualThemeVariantProperty)
{
ActualThemeVariantChanged?.Invoke(this, EventArgs.Empty);
}
@@ -350,8 +334,13 @@ namespace Avalonia
private void OnColorValuesChanged(object? sender, PlatformColorValues e)
{
- if ((RequestedThemeVariant ?? ThemeVariant.Default) == ThemeVariant.Default)
- SetValue(ActualThemeVariantProperty, (ThemeVariant)e.ThemeVariant);
+ ThemeVariant.UpdateActualThemeVariant(this);
+ }
+
+ internal void InitializeThemeVariant()
+ {
+ PlatformSettings?.ColorValuesChanged += OnColorValuesChanged;
+ ThemeVariant.UpdateActualThemeVariant(this);
}
}
}
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index 53f1df7358..2a67934a98 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs
index 7062a9af81..76d7220ee6 100644
--- a/src/Avalonia.Controls/Calendar/Calendar.cs
+++ b/src/Avalonia.Controls/Calendar/Calendar.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Globalization;
using Avalonia.Automation.Peers;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
@@ -353,6 +354,43 @@ namespace Avalonia.Controls
set => SetValue(HeaderBackgroundProperty, value);
}
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty IsWeekNumberVisibleProperty =
+ AvaloniaProperty.Register(nameof(IsWeekNumberVisible));
+
+ ///
+ /// Gets or sets a value indicating whether week numbers are shown in the month view.
+ ///
+ public bool IsWeekNumberVisible
+ {
+ get => GetValue(IsWeekNumberVisibleProperty);
+ set => SetValue(IsWeekNumberVisibleProperty, value);
+ }
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty WeekNumberRuleProperty =
+ AvaloniaProperty.Register(
+ nameof(WeekNumberRule),
+ defaultValue: DateTimeHelper.GetCurrentDateFormat().CalendarWeekRule);
+
+ ///
+ /// Gets or sets the rule used to determine the first week of the year for week number display.
+ /// The default is taken from the current culture.
+ ///
+ ///
+ /// Use WeekNumberRule = in combination with FirstDayOfWeek =
+ /// for ISO 8601 week numbering. (see also: )
+ ///
+ public CalendarWeekRule WeekNumberRule
+ {
+ get => GetValue(WeekNumberRuleProperty);
+ set => SetValue(WeekNumberRuleProperty, value);
+ }
+
public static readonly StyledProperty DisplayModeProperty =
AvaloniaProperty.Register(
nameof(DisplayMode),
@@ -421,6 +459,7 @@ namespace Avalonia.Controls
}
}
}
+ monthControl?.UpdateWeekNumberLabelsVisibility();
OnDisplayModeChanged(new CalendarModeChangedEventArgs((CalendarMode)e.OldValue, mode));
}
private static bool IsValidDisplayMode(CalendarMode mode)
@@ -2209,6 +2248,8 @@ namespace Avalonia.Controls
DisplayDateProperty.Changed.AddClassHandler((x, e) => x.OnDisplayDateChanged(e));
DisplayDateStartProperty.Changed.AddClassHandler((x, e) => x.OnDisplayDateStartChanged(e));
DisplayDateEndProperty.Changed.AddClassHandler((x, e) => x.OnDisplayDateEndChanged(e));
+ IsWeekNumberVisibleProperty.Changed.AddClassHandler((x, _) => x.UpdateMonths());
+ WeekNumberRuleProperty.Changed.AddClassHandler((x, _) => x.UpdateMonths());
KeyDownEvent.AddClassHandler((x, e) => x.Calendar_KeyDown(e));
KeyUpEvent.AddClassHandler((x, e) => x.Calendar_KeyUp(e));
}
diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs
index e33298023f..1e703e8a42 100644
--- a/src/Avalonia.Controls/Calendar/CalendarItem.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs
@@ -1,4 +1,4 @@
-// (c) Copyright Microsoft Corporation.
+// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
@@ -19,12 +19,13 @@ namespace Avalonia.Controls.Primitives
/// Represents the currently displayed month or year on a
/// .
///
- [TemplatePart(PART_ElementHeaderButton, typeof(Button))]
- [TemplatePart(PART_ElementMonthView, typeof(Grid))]
- [TemplatePart(PART_ElementNextButton, typeof(Button))]
- [TemplatePart(PART_ElementPreviousButton, typeof(Button))]
- [TemplatePart(PART_ElementYearView, typeof(Grid))]
- [PseudoClasses(":calendardisabled")]
+ [TemplatePart(PART_ElementHeaderButton, typeof(Button))]
+ [TemplatePart(PART_ElementMonthView, typeof(Grid))]
+ [TemplatePart(PART_ElementNextButton, typeof(Button))]
+ [TemplatePart(PART_ElementPreviousButton, typeof(Button))]
+ [TemplatePart(PART_ElementYearView, typeof(Grid))]
+ [TemplatePart(PART_ElementWeekNumberLabels, typeof(Grid))]
+ [PseudoClasses(":calendardisabled", ":hasweeknumbers")]
public sealed class CalendarItem : TemplatedControl
{
///
@@ -37,6 +38,7 @@ namespace Avalonia.Controls.Primitives
private const string PART_ElementNextButton = "PART_NextButton";
private const string PART_ElementMonthView = "PART_MonthView";
private const string PART_ElementYearView = "PART_YearView";
+ private const string PART_ElementWeekNumberLabels = "PART_ElementWeekNumberLabels";
private Button? _headerButton;
private Button? _nextButton;
@@ -164,6 +166,11 @@ namespace Avalonia.Controls.Primitives
///
internal Grid? YearView { get; set; }
+ ///
+ /// Gets the Grid that hosts the week number labels when in month mode.
+ ///
+ private Grid? WeekNumberLabels { get; set; }
+
private void PopulateGrids()
{
if (MonthView != null)
@@ -210,6 +217,21 @@ namespace Avalonia.Controls.Primitives
MonthView.Children.AddRange(children);
}
+ if (WeekNumberLabels != null)
+ {
+ using var children = new PooledList(Calendar.RowsPerMonth);
+
+ for (int i = 1; i < Calendar.RowsPerMonth; i++)
+ {
+ var cell = new ContentControl();
+ cell.SetValue(Grid.RowProperty, i);
+ cell.TemplatedParent = this;
+ children.Add(cell);
+ }
+
+ WeekNumberLabels.Children.AddRange(children);
+ }
+
if (YearView != null)
{
var childCount = Calendar.RowsPerYear * Calendar.ColumnsPerYear;
@@ -254,6 +276,7 @@ namespace Avalonia.Controls.Primitives
NextButton = e.NameScope.Find
[PseudoClasses(pcNormal, pcMaximized, pcFullscreen, pcHasShadow, pcHasBorder, pcHasTitlebar,
- pcHasMaximize, pcHasFullscreen, pcHasMinimize)]
+ pcHasMaximize, pcHasFullscreen, pcHasMinimize, pcHasClose, pcHasTitle)]
[TemplatePart(PART_CloseButton, typeof(Button))]
[TemplatePart(PART_MinimizeButton, typeof(Button))]
[TemplatePart(PART_MaximizeButton, typeof(Button))]
@@ -36,6 +36,8 @@ public class WindowDrawnDecorations : StyledElement
internal const string pcHasMaximize = ":has-maximize";
internal const string pcHasFullscreen = ":has-fullscreen";
internal const string pcHasMinimize = ":has-minimize";
+ internal const string pcHasClose = ":has-close";
+ internal const string pcHasTitle = ":has-title";
// Template part names for caption buttons
internal const string PART_CloseButton = "PART_CloseButton";
@@ -126,6 +128,13 @@ public class WindowDrawnDecorations : StyledElement
public static readonly StyledProperty TitleProperty =
AvaloniaProperty.Register(nameof(Title));
+ ///
+ /// Defines the TitleBarDecorations attached property.
+ ///
+ public static readonly AttachedProperty TitleBarDecorationsProperty =
+ AvaloniaProperty.RegisterAttached(
+ "TitleBarDecorations", TitleBarDecorations.All);
+
///
/// Defines the property.
///
@@ -244,6 +253,7 @@ public class WindowDrawnDecorations : StyledElement
///
/// Gets or sets the window title displayed in the decorations.
+ /// Mirrors the value set on the host .
///
public string? Title
{
@@ -251,6 +261,31 @@ public class WindowDrawnDecorations : StyledElement
set => SetValue(TitleProperty, value);
}
+ ///
+ /// Gets which title bar elements to display.
+ ///
+ public static TitleBarDecorations GetTitleBarDecorations(StyledElement element)
+ => element.GetValue(TitleBarDecorationsProperty);
+
+ ///
+ /// Sets which title bar elements to display.
+ ///
+ ///
+ /// Set this property on a to control the elements displayed in its drawn title bar.
+ ///
+ public static void SetTitleBarDecorations(StyledElement element, TitleBarDecorations value)
+ => element.SetValue(TitleBarDecorationsProperty, value);
+
+ ///
+ /// Gets or sets which title bar elements are requested to be displayed.
+ /// Mirrors the value set on the host .
+ ///
+ public TitleBarDecorations TitleBarDecorations
+ {
+ get => GetValue(TitleBarDecorationsProperty);
+ set => SetValue(TitleBarDecorationsProperty, value);
+ }
+
///
/// Gets or sets which decoration parts are enabled.
/// Set by Window based on platform capabilities and user preferences.
@@ -334,6 +369,7 @@ public class WindowDrawnDecorations : StyledElement
x.UpdateEffectiveGeometry();
});
+ TitleBarDecorationsProperty.Changed.AddClassHandler((x, _) => x.UpdateTitleBarDecorationsPseudoClasses());
DefaultTitleBarHeightProperty.Changed.AddClassHandler((x, _) => x.UpdateEffectiveGeometry());
DefaultFrameThicknessProperty.Changed.AddClassHandler((x, _) => x.UpdateEffectiveGeometry());
DefaultShadowThicknessProperty.Changed.AddClassHandler((x, _) => x.UpdateEffectiveGeometry());
@@ -395,6 +431,8 @@ public class WindowDrawnDecorations : StyledElement
Disposable.Create(() => window.AllowedWindowActionsChanged -= OnAllowedWindowActionsChanged),
window.GetObservable(Window.TitleProperty)
.Subscribe(title => SetCurrentValue(TitleProperty, title)),
+ window.GetObservable(TitleBarDecorationsProperty)
+ .Subscribe(hints => SetCurrentValue(TitleBarDecorationsProperty, hints)),
window.GetObservable(Window.CanMaximizeProperty)
.Subscribe(_ =>
{
@@ -415,7 +453,7 @@ public class WindowDrawnDecorations : StyledElement
}),
};
- UpdateAllowedActionsPseudoClasses();
+ UpdateTitleBarDecorationsPseudoClasses();
UpdateMaximizeButtonState();
UpdateMinimizeButtonState();
UpdateFullScreenButtonState();
@@ -592,18 +630,25 @@ public class WindowDrawnDecorations : StyledElement
private void OnAllowedWindowActionsChanged(PlatformAllowedWindowActions actions)
{
- UpdateAllowedActionsPseudoClasses();
+ UpdateTitleBarDecorationsPseudoClasses();
UpdateMaximizeButtonState();
UpdateMinimizeButtonState();
UpdateFullScreenButtonState();
}
- private void UpdateAllowedActionsPseudoClasses()
+ private void UpdateTitleBarDecorationsPseudoClasses()
{
var actions = EffectiveAllowedActions;
- PseudoClasses.Set(pcHasMaximize, actions.HasFlag(PlatformAllowedWindowActions.Maximize));
- PseudoClasses.Set(pcHasFullscreen, actions.HasFlag(PlatformAllowedWindowActions.Fullscreen));
- PseudoClasses.Set(pcHasMinimize, actions.HasFlag(PlatformAllowedWindowActions.Minimize));
+ var hints = TitleBarDecorations;
+
+ PseudoClasses.Set(pcHasMaximize, actions.HasFlag(PlatformAllowedWindowActions.Maximize)
+ && hints.HasFlag(TitleBarDecorations.MaximizeButton));
+ PseudoClasses.Set(pcHasFullscreen, actions.HasFlag(PlatformAllowedWindowActions.Fullscreen)
+ && hints.HasFlag(TitleBarDecorations.FullScreenButton));
+ PseudoClasses.Set(pcHasMinimize, actions.HasFlag(PlatformAllowedWindowActions.Minimize)
+ && hints.HasFlag(TitleBarDecorations.MinimizeButton));
+ PseudoClasses.Set(pcHasClose, hints.HasFlag(TitleBarDecorations.CloseButton));
+ PseudoClasses.Set(pcHasTitle, hints.HasFlag(TitleBarDecorations.Title));
}
private void UpdateEffectiveGeometry()
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index b9290d3c10..2cef78e6bd 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -102,7 +102,7 @@ namespace Avalonia.Controls
if (template is not null) return template;
if(obj is ComboBox comboBox && template is null)
{
- return comboBox.ItemTemplate;
+ return comboBox.GetEffectiveItemTemplate();
}
return template;
}
@@ -425,6 +425,10 @@ namespace Avalonia.Controls
{
CoerceValue(SelectionBoxItemTemplateProperty);
}
+ else if (change.Property == SelectionBoxItemTemplateProperty)
+ {
+ UpdateSelectionBoxItem(SelectedItem);
+ }
else if (change.Property == IsEditableProperty && change.GetNewValue())
{
UpdateInputTextFromSelection(SelectedItem);
@@ -444,6 +448,10 @@ namespace Avalonia.Controls
else if (change.Property == DisplayMemberBindingProperty)
{
HandleTextValueBindingValueChanged(null, change);
+ // The base handler invalidates the cached template: run it before coercing.
+ base.OnPropertyChanged(change);
+ CoerceValue(SelectionBoxItemTemplateProperty);
+ return;
}
else if (change.Property == TextSearch.TextBindingProperty)
{
@@ -533,18 +541,24 @@ namespace Avalonia.Controls
private void UpdateSelectionBoxItem(object? item)
{
- var contentControl = item as IContentControl;
-
- if (contentControl != null)
+ if (item is IContentControl contentControl)
{
item = contentControl.Content;
}
- var control = item as Control;
+ if (item is null)
+ {
+ SelectionBoxItem = null;
+ return;
+ }
- if (control != null)
+ if (SelectionBoxItemTemplate is not null)
{
- if (VisualRoot is object)
+ SelectionBoxItem = item;
+ }
+ else if (item is Control control)
+ {
+ if (VisualRoot is not null)
{
control.Measure(Size.Infinity);
@@ -565,22 +579,7 @@ namespace Avalonia.Controls
}
else
{
- if (item is not null && ItemTemplate is null && SelectionBoxItemTemplate is null && DisplayMemberBinding is { } binding)
- {
- var template = new FuncDataTemplate((_, _) =>
- new TextBlock
- {
- [TextBlock.DataContextProperty] = item,
- [!TextBlock.TextProperty] = binding,
- });
- var text = template.Build(item);
- SelectionBoxItem = text;
- }
- else
- {
- SelectionBoxItem = item;
- }
-
+ SelectionBoxItem = item;
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
index 2f406252f7..c4206c7315 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
@@ -75,6 +75,21 @@ namespace Avalonia.Controls
public static readonly StyledProperty YearVisibleProperty =
AvaloniaProperty.Register(nameof(YearVisible), true);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty VerticalContentAlignmentProperty =
+ ContentControl.VerticalContentAlignmentProperty.AddOwner();
+
+ ///
+ /// Gets or sets the vertical alignment of the content within the control.
+ ///
+ public VerticalAlignment VerticalContentAlignment
+ {
+ get => GetValue(VerticalContentAlignmentProperty);
+ set => SetValue(VerticalContentAlignmentProperty, value);
+ }
+
///
/// Defines the Property
///
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index 95d9e82782..7c6f96247f 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -50,6 +50,20 @@ namespace Avalonia.Controls
public static readonly StyledProperty ClockIdentifierProperty =
AvaloniaProperty.Register(nameof(ClockIdentifier), "12HourClock", coerce: CoerceClockIdentifier);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty VerticalContentAlignmentProperty =
+ ContentControl.VerticalContentAlignmentProperty.AddOwner();
+
+ ///
+ /// Gets or sets the vertical alignment of the content within the control.
+ ///
+ public VerticalAlignment VerticalContentAlignment
+ {
+ get => GetValue(VerticalContentAlignmentProperty);
+ set => SetValue(VerticalContentAlignmentProperty, value);
+ }
///
/// Defines the property
///
diff --git a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
index 59718c3e3f..b65db54a93 100644
--- a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
+++ b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
@@ -69,7 +69,7 @@ namespace Avalonia.Controls.Embedding
public void Dispose()
{
PlatformImpl?.Dispose();
- LayoutManager?.Dispose();
+ EnsureClosed();
}
}
}
diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
index a87e36d00d..65ca492f1f 100644
--- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
+++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
@@ -35,6 +35,7 @@ namespace Avalonia.Controls.Embedding.Offscreen
public void Dispose()
{
PlatformImpl?.Dispose();
+ EnsureClosed();
}
}
}
diff --git a/src/Avalonia.Controls/FlexPanel/Flex.cs b/src/Avalonia.Controls/FlexPanel/Flex.cs
new file mode 100644
index 0000000000..965e3da2a2
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/Flex.cs
@@ -0,0 +1,274 @@
+using System;
+
+using Avalonia.Layout;
+
+namespace Avalonia.Controls
+{
+ ///
+ /// Provides attached properties for controlling the layout behavior of child elements within a .
+ ///
+ public static class Flex
+ {
+ ///
+ /// Defines an attached property to control the cross-axis alignment of a specific child in a flex layout.
+ ///
+ public static readonly AttachedProperty AlignSelfProperty =
+ AvaloniaProperty.RegisterAttached("AlignSelf", typeof(Flex));
+
+ ///
+ /// Defines an attached property to control the order of a specific child in a flex layout.
+ ///
+ public static readonly AttachedProperty OrderProperty =
+ AvaloniaProperty.RegisterAttached("Order", typeof(Flex));
+
+ ///
+ /// Defines an attached property to control the initial main-axis size of a specific child in a flex layout.
+ ///
+ public static readonly AttachedProperty BasisProperty =
+ AvaloniaProperty.RegisterAttached("Basis", typeof(Flex), FlexBasis.Auto);
+
+ ///
+ /// Defines an attached property to control the factor by which a specific child can shrink
+ /// along the main-axis in a flex layout.
+ ///
+ public static readonly AttachedProperty ShrinkProperty =
+ AvaloniaProperty.RegisterAttached("Shrink", typeof(Flex), 1.0, validate: v => v >= 0.0);
+
+ ///
+ /// Defines an attached property to control the factor by which a specific child can grow
+ /// along the main-axis in a flex layout.
+ ///
+ public static readonly AttachedProperty GrowProperty =
+ AvaloniaProperty.RegisterAttached("Grow", typeof(Flex), 0.0, validate: v => v >= 0.0);
+
+ internal static readonly AttachedProperty BaseLengthProperty =
+ AvaloniaProperty.RegisterAttached("BaseLength", typeof(Flex), 0.0);
+
+ internal static readonly AttachedProperty CurrentLengthProperty =
+ AvaloniaProperty.RegisterAttached("CurrentLength", typeof(Flex), 0.0);
+
+ ///
+ /// Gets the cross-axis alignment override for a child item in a
+ ///
+ ///
+ /// This property is used to override the property for a specific child.
+ /// When omitted, in not overridden.
+ /// Equivalent to CSS align-self property.
+ ///
+ public static FlexAlignItems? GetAlignSelf(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(AlignSelfProperty);
+ }
+
+ ///
+ /// Sets the cross-axis alignment override for a child item in a
+ ///
+ ///
+ /// This property is used to override the property for a specific child.
+ /// When omitted, in not overridden.
+ /// Equivalent to CSS align-self property.
+ ///
+ public static void SetAlignSelf(Layoutable layoutable, FlexAlignItems? value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(AlignSelfProperty, value);
+ }
+
+ ///
+ /// Retrieves the order in which a child item appears within the .
+ ///
+ ///
+ /// A lower order value means the item will be positioned earlier within the container.
+ /// Items with the same order value are laid out in their source document order.
+ /// When omitted, it is set to 0.
+ /// Equivalent to CSS order property.
+ ///
+ public static int GetOrder(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(OrderProperty);
+ }
+
+ ///
+ /// Sets the order in which a child item appears within the .
+ ///
+ ///
+ /// A lower order value means the item will be positioned earlier within the container.
+ /// Items with the same order value are laid out in their source document order.
+ /// When omitted, it is set to 0.
+ /// Equivalent to CSS order property.
+ ///
+ public static void SetOrder(Layoutable layoutable, int value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(OrderProperty, value);
+ }
+
+ ///
+ /// Gets the initial size along the main-axis of an item in a ,
+ /// before free space is distributed according to the flex factors.
+ ///
+ ///
+ /// Either automatic size, a fixed length, or a percentage of the container's size.
+ /// When omitted, it is set to .
+ /// Equivalent to CSS flex-basis property.
+ ///
+ public static FlexBasis GetBasis(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(BasisProperty);
+ }
+
+ ///
+ /// Sets the initial size along the main-axis of an item in a ,
+ /// before free space is distributed according to the flex factors.
+ ///
+ ///
+ /// Either automatic size, a fixed length, or a percentage of the container's size.
+ /// When omitted, it is set to .
+ /// Equivalent to CSS flex-basis property.
+ ///
+ public static void SetBasis(Layoutable layoutable, FlexBasis value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(BasisProperty, value);
+ }
+
+ ///
+ /// Gets the factor by which an item can shrink along the main-axis,
+ /// relative to other items in a .
+ ///
+ ///
+ /// When omitted, it is set to 1.
+ /// Equivalent to CSS flex-shrink property.
+ ///
+ public static double GetShrink(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(ShrinkProperty);
+ }
+
+ ///
+ /// Sets the factor by which an item can shrink along the main-axis,
+ /// relative to other items in a .
+ ///
+ ///
+ /// When omitted, it is set to 1.
+ /// Equivalent to CSS flex-shrink property.
+ ///
+ public static void SetShrink(Layoutable layoutable, double value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(ShrinkProperty, value);
+ }
+
+ ///
+ /// Gets the factor by which an item can grow along the main-axis,
+ /// relative to other items in a .
+ ///
+ ///
+ /// When omitted, it is set to 0.
+ /// Equivalent to CSS flex-grow property.
+ ///
+ public static double GetGrow(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(GrowProperty);
+ }
+
+ ///
+ /// Sets the factor by which an item can grow along the main-axis,
+ /// relative to other items in a .
+ ///
+ ///
+ /// When omitted, it is set to 0.
+ /// Equivalent to CSS flex-grow property.
+ ///
+ public static void SetGrow(Layoutable layoutable, double value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(GrowProperty, value);
+ }
+
+ internal static double GetBaseLength(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(BaseLengthProperty);
+ }
+
+ internal static void SetBaseLength(Layoutable layoutable, double value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(BaseLengthProperty, value);
+ }
+
+ internal static double GetCurrentLength(Layoutable layoutable)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ return layoutable.GetValue(CurrentLengthProperty);
+ }
+
+ internal static void SetCurrentLength(Layoutable layoutable, double value)
+ {
+ if (layoutable is null)
+ {
+ throw new ArgumentNullException(nameof(layoutable));
+ }
+
+ layoutable.SetValue(CurrentLengthProperty, value);
+ }
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexAlignContent.cs b/src/Avalonia.Controls/FlexPanel/FlexAlignContent.cs
new file mode 100644
index 0000000000..ac60c76990
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexAlignContent.cs
@@ -0,0 +1,46 @@
+namespace Avalonia.Controls
+{
+ ///
+ /// Defines the alignment mode of the lines inside a along the cross-axis.
+ ///
+ public enum FlexAlignContent
+ {
+ ///
+ /// Lines are packed toward the start of the container.
+ ///
+ FlexStart,
+
+ ///
+ /// Lines are packed toward the end of the container.
+ ///
+ FlexEnd,
+
+ ///
+ /// Lines are packed toward the center of the container
+ ///
+ Center,
+
+ ///
+ /// Lines are stretched to take up the remaining space.
+ ///
+ ///
+ /// This is the default value.
+ ///
+ Stretch,
+
+ ///
+ /// Lines are evenly distributed in the container, with no space on either end.
+ ///
+ SpaceBetween,
+
+ ///
+ /// Lines are evenly distributed in the container, with half-size spaces on either end.
+ ///
+ SpaceAround,
+
+ ///
+ /// Lines are evenly distributed in the container, with equal-size spaces between each line and on either end.
+ ///
+ SpaceEvenly
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexAlignItems.cs b/src/Avalonia.Controls/FlexPanel/FlexAlignItems.cs
new file mode 100644
index 0000000000..09f3113e0f
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexAlignItems.cs
@@ -0,0 +1,38 @@
+using System.Diagnostics.CodeAnalysis;
+
+namespace Avalonia.Controls
+{
+ ///
+ /// Defines the alignment mode along the cross-axis of child items.
+ ///
+ [SuppressMessage("Naming", "CA1717:Only FlagsAttribute enums should have plural names")]
+ public enum FlexAlignItems
+ {
+ ///
+ /// Items are aligned to the cross-axis start margin edge of the line.
+ ///
+ FlexStart,
+
+ ///
+ /// Items are aligned to the cross-axis end margin edge of the line.
+ ///
+ FlexEnd,
+
+ ///
+ /// Items are aligned to the cross-axis center of the line.
+ ///
+ ///
+ /// If the cross size of the line is less than that of the child item,
+ /// it will overflow equally in both directions.
+ ///
+ Center,
+
+ ///
+ /// Items are stretched to fill the cross size of the line.
+ ///
+ ///
+ /// This is the default value.
+ ///
+ Stretch
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexBasis.cs b/src/Avalonia.Controls/FlexPanel/FlexBasis.cs
new file mode 100644
index 0000000000..c6f9848a41
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexBasis.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+
+namespace Avalonia.Controls
+{
+ ///
+ /// Specifies the initial size of a flex item.
+ ///
+ public readonly partial struct FlexBasis : IEquatable
+ {
+ ///
+ /// Gets the value of the . The meaning of this value depends on the
+ ///
+ public double Value { get; }
+
+ ///
+ /// Gets the . This determines how the value affects the size of the flex item
+ ///
+ public FlexBasisKind Kind { get; }
+
+ ///
+ /// Initializes an instance of and sets the value and
+ ///
+ /// The value of the
+ /// The . This determines how the value affects the size of the flex item/>
+ ///
+ public FlexBasis(double value, FlexBasisKind kind)
+ {
+ if (value < 0 || double.IsNaN(value) || double.IsInfinity(value))
+ throw new ArgumentException($"Invalid basis value: {value}", nameof(value));
+ if (kind < FlexBasisKind.Auto || kind > FlexBasisKind.Relative)
+ throw new ArgumentException($"Invalid basis kind: {kind}", nameof(kind));
+ Value = value;
+ Kind = kind;
+ }
+
+ ///
+ /// Initializes an instance of and sets the absolute value
+ ///
+ /// The absolute value of the
+ ///
+ public FlexBasis(double value) : this(value, FlexBasisKind.Absolute) { }
+
+ ///
+ /// Gets a instance that represents the "auto" value, which means the size of the flex item is determined by its content or other factors.
+ ///
+ public static FlexBasis Auto => new(0.0, FlexBasisKind.Auto);
+
+ ///
+ /// Gets a value indicating whether the is set to "auto".
+ ///
+ public bool IsAuto => Kind == FlexBasisKind.Auto;
+
+ ///
+ /// Gets a value indicating whether the is set to an absolute value.
+ ///
+ public bool IsAbsolute => Kind == FlexBasisKind.Absolute;
+
+ ///
+ /// Gets a value indicating whether the is set to a relative value.
+ ///
+ public bool IsRelative => Kind == FlexBasisKind.Relative;
+
+ [SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
+ public bool Equals(FlexBasis other) =>
+ (IsAuto && other.IsAuto) || (Value == other.Value && Kind == other.Kind);
+
+ public override bool Equals(object? obj) =>
+ obj is FlexBasis other && Equals(other);
+
+ public override int GetHashCode() =>
+ (Value, Kind).GetHashCode();
+
+ public static bool operator ==(FlexBasis left, FlexBasis right) =>
+ left.Equals(right);
+
+ public static bool operator !=(FlexBasis left, FlexBasis right) =>
+ !left.Equals(right);
+
+ public override string ToString()
+ {
+ return Kind switch
+ {
+ FlexBasisKind.Auto => "Auto",
+ FlexBasisKind.Absolute => FormattableString.Invariant($"{Value:G17}"),
+ FlexBasisKind.Relative => FormattableString.Invariant($"{Value * 100:G17}%"),
+ _ => throw new InvalidOperationException(),
+ };
+ }
+
+ ///
+ /// Converts a string flex-basis value to a instance.
+ ///
+ /// The value to parse.
+ ///
+ public static FlexBasis Parse(string str)
+ {
+ var span = str.AsSpan().Trim();
+ if (string.Equals(str, "AUTO", StringComparison.OrdinalIgnoreCase))
+ {
+ return Auto;
+ }
+ else if (span.EndsWith("%") && double.TryParse(span[..^1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var val))
+ {
+ return new FlexBasis(val / 100, FlexBasisKind.Relative);
+ }
+ else if (double.TryParse(str, NumberStyles.Float, CultureInfo.InvariantCulture, out var value))
+ {
+ return new FlexBasis(value, FlexBasisKind.Absolute);
+ }
+
+ throw new ArgumentException($"Value '{str}' is not a valid flex-basis value. Valid values are 'auto', a number (e.g., '100'), or a percentage (e.g., '50%').", nameof(str));
+ }
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexBasisKind.cs b/src/Avalonia.Controls/FlexPanel/FlexBasisKind.cs
new file mode 100644
index 0000000000..b43781d28c
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexBasisKind.cs
@@ -0,0 +1,23 @@
+namespace Avalonia.Controls
+{
+ ///
+ /// Determines how affects the size of the flex item
+ ///
+ public enum FlexBasisKind
+ {
+ ///
+ /// Uses the measured Width and Height of the to determine the initial size of the item.
+ ///
+ Auto,
+
+ ///
+ /// The initial size of the item is set to the value.
+ ///
+ Absolute,
+
+ ///
+ /// Indicates the value is a percentage, and the size of the flex item is scaled by it.
+ ///
+ Relative,
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexDirection.cs b/src/Avalonia.Controls/FlexPanel/FlexDirection.cs
new file mode 100644
index 0000000000..ed8a59e4b3
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexDirection.cs
@@ -0,0 +1,31 @@
+namespace Avalonia.Controls
+{
+ ///
+ /// Describes the orientation and direction along which items are placed inside the
+ ///
+ public enum FlexDirection
+ {
+ ///
+ /// Items are placed along the horizontal axis, starting from the left
+ ///
+ ///
+ /// This is the default value.
+ ///
+ Row,
+
+ ///
+ /// Items are placed along the horizontal axis, starting from the right
+ ///
+ RowReverse,
+
+ ///
+ /// Items are placed along the vertical axis, starting from the top
+ ///
+ Column,
+
+ ///
+ /// Items are placed along the vertical axis, starting from the bottom
+ ///
+ ColumnReverse
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexJustifyContent.cs b/src/Avalonia.Controls/FlexPanel/FlexJustifyContent.cs
new file mode 100644
index 0000000000..24bb56709a
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexJustifyContent.cs
@@ -0,0 +1,53 @@
+namespace Avalonia.Controls
+{
+
+ ///
+ /// Describes the main-axis alignment of items inside a line.
+ ///
+ public enum FlexJustifyContent
+ {
+ ///
+ /// Child items are packed toward the start of the line.
+ ///
+ ///
+ /// This is the default value.
+ ///
+ FlexStart,
+
+ ///
+ /// Child items are packed toward the end of the line.
+ ///
+ FlexEnd,
+
+ ///
+ /// Child items are packed toward the center of the line.
+ ///
+ ///
+ /// If the leftover free-space is negative, the child items will overflow equally in both directions.
+ ///
+ Center,
+
+ ///
+ /// Child items are evenly distributed in the line, with no space on either end.
+ ///
+ ///
+ /// If the leftover free-space is negative or there is only a single child item on the line,
+ /// this value is identical to .
+ ///
+ SpaceBetween,
+
+ ///
+ /// Child items are evenly distributed in the line, with half-size spaces on either end.
+ ///
+ ///
+ /// If the leftover free-space is negative or there is only a single child item on the line,
+ /// this value is identical to .
+ ///
+ SpaceAround,
+
+ ///
+ /// Child items are evenly distributed in the line, with equal-size spaces between each item and on either end.
+ ///
+ SpaceEvenly
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexPanel.cs b/src/Avalonia.Controls/FlexPanel/FlexPanel.cs
new file mode 100644
index 0000000000..9efdc04901
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexPanel.cs
@@ -0,0 +1,661 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using Avalonia.Layout;
+using Avalonia.Reactive;
+using Avalonia.Utilities;
+
+namespace Avalonia.Controls
+{
+ ///
+ /// A panel that arranges child controls using CSS FlexBox principles.
+ /// It organizes child items in one or more lines along a main-axis (either row or column)
+ /// and provides advanced control over their sizing and layout.
+ ///
+ ///
+ /// See CSS FlexBox specification: https://www.w3.org/TR/css-flexbox-1
+ ///
+ public sealed class FlexPanel : Panel
+ {
+ private static readonly Func s_getOrder = x => Flex.GetOrder(x);
+ private static readonly Func s_isVisible = x => x.IsVisible;
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty DirectionProperty =
+ AvaloniaProperty.Register(nameof(Direction));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty JustifyContentProperty =
+ AvaloniaProperty.Register(nameof(JustifyContent));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty AlignItemsProperty =
+ AvaloniaProperty.Register(nameof(AlignItems), FlexAlignItems.Stretch);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty AlignContentProperty =
+ AvaloniaProperty.Register(nameof(AlignContent), FlexAlignContent.Stretch);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty WrapProperty =
+ AvaloniaProperty.Register(nameof(Wrap));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty ColumnSpacingProperty =
+ AvaloniaProperty.Register(nameof(ColumnSpacing));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty RowSpacingProperty =
+ AvaloniaProperty.Register(nameof(RowSpacing));
+
+ private FlexLayoutState _state = new FlexLayoutState();
+ private Dictionary _childVisibilitySubscriptions = new Dictionary();
+ private Layoutable[]? _visibleChildren;
+
+ static FlexPanel()
+ {
+ AffectsMeasure(
+ DirectionProperty,
+ JustifyContentProperty,
+ WrapProperty,
+ ColumnSpacingProperty,
+ RowSpacingProperty);
+
+ AffectsArrange(
+ AlignItemsProperty,
+ AlignContentProperty);
+
+ AffectsParentMeasure(
+ HorizontalAlignmentProperty,
+ VerticalAlignmentProperty,
+ Flex.OrderProperty,
+ Flex.BasisProperty,
+ Flex.ShrinkProperty,
+ Flex.GrowProperty);
+
+ AffectsParentArrange(
+ Flex.AlignSelfProperty);
+ }
+
+ ///
+ /// Gets or sets the direction of the 's main-axis,
+ /// determining the orientation in which child controls are laid out.
+ ///
+ ///
+ /// The default value is .
+ /// Equivalent to CSS flex-direction property
+ ///
+ public FlexDirection Direction
+ {
+ get => GetValue(DirectionProperty);
+ set => SetValue(DirectionProperty, value);
+ }
+
+ ///
+ /// Gets or sets the main-axis alignment of child items inside a line of the .
+ /// Typically used to distribute extra free space leftover after flexible lengths and margins have been resolved.
+ ///
+ ///
+ /// The default value is .
+ /// Equivalent to CSS justify-content property.
+ ///
+ public FlexJustifyContent JustifyContent
+ {
+ get => GetValue(JustifyContentProperty);
+ set => SetValue(JustifyContentProperty, value);
+ }
+
+ ///
+ /// Gets or sets the cross-axis alignment of all child items inside a line of the .
+ /// Similar to , but in the perpendicular direction.
+ ///
+ ///
+ /// The default value is .
+ /// Equivalent to CSS align-items property.
+ ///
+ public FlexAlignItems AlignItems
+ {
+ get => GetValue(AlignItemsProperty);
+ set => SetValue(AlignItemsProperty, value);
+ }
+
+ ///
+ /// Gets or sets the cross-axis alignment of lines in the when there is extra space.
+ /// Similar to , but for entire lines.
+ /// property set to mode
+ /// allows controls to be arranged on multiple lines.
+ ///
+ ///
+ /// The default value is .
+ /// Equivalent to CSS align-content property.
+ ///
+ public FlexAlignContent AlignContent
+ {
+ get => GetValue(AlignContentProperty);
+ set => SetValue(AlignContentProperty, value);
+ }
+
+ ///
+ /// Gets or sets the wrap mode, controlling whether the is single-line or multi-line.
+ /// Additionally, it determines the cross-axis stacking direction for new lines.
+ ///
+ ///
+ /// The default value is .
+ /// Equivalent to CSS flex-wrap property.
+ ///
+ public FlexWrap Wrap
+ {
+ get => GetValue(WrapProperty);
+ set => SetValue(WrapProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minimum horizontal spacing between child items or lines,
+ /// depending on main-axis direction of the .
+ ///
+ ///
+ /// The default value is 0.
+ /// Similar to CSS column-gap property.
+ ///
+ public double ColumnSpacing
+ {
+ get => GetValue(ColumnSpacingProperty);
+ set => SetValue(ColumnSpacingProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minimum vertical spacing between child items or lines,
+ /// depending on main-axis direction of the .
+ ///
+ ///
+ /// The default value is 0.
+ /// Similar to CSS row-gap property.
+ ///
+ public double RowSpacing
+ {
+ get => GetValue(RowSpacingProperty);
+ set => SetValue(RowSpacingProperty, value);
+ }
+
+ ///
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ if (_visibleChildren is not { Length: > 0 } children)
+ {
+ _state.Lines.Clear();
+ return availableSize;
+ }
+
+ var isColumn = Direction is FlexDirection.Column or FlexDirection.ColumnReverse;
+
+ var max = Uv.FromSize(availableSize, isColumn);
+ var spacing = Uv.FromSize(ColumnSpacing, RowSpacing, isColumn);
+
+ LineData lineData = default;
+ var (childIndex, firstChildIndex, itemIndex) = (0, 0, 0);
+
+ _state.Lines.Clear();
+
+ double panelSizeU = 0;
+ Func maxSelector = l => l.U + (l.Count - 1) * spacing.U;
+
+ foreach (var element in children)
+ {
+ var size = MeasureChild(element, max, isColumn);
+
+ if (Wrap != FlexWrap.NoWrap && MathUtilities.GreaterThanOrClose(lineData.U + size.U + itemIndex * spacing.U, max.U))
+ {
+ var line = new FlexLine(firstChildIndex, childIndex - 1, lineData);
+ _state.Lines.Add(line);
+ lineData = default;
+ firstChildIndex = childIndex;
+ itemIndex = 0;
+
+ panelSizeU = Math.Max(panelSizeU, maxSelector(line));
+ }
+
+ lineData.U += size.U;
+ lineData.V = Math.Max(lineData.V, size.V);
+ lineData.Shrink += Flex.GetShrink(element);
+ lineData.Grow += Flex.GetGrow(element);
+ lineData.AutoMargins += GetItemAutoMargins(element, isColumn);
+ itemIndex++;
+ childIndex++;
+ }
+
+ if (itemIndex != 0)
+ {
+ var line = new FlexLine(firstChildIndex, firstChildIndex + itemIndex - 1, lineData);
+ _state.Lines.Add(line);
+ panelSizeU = Math.Max(panelSizeU, maxSelector(line));
+ }
+
+ var totalSpacingV = (_state.Lines.Count - 1) * spacing.V;
+
+ // Resizing along main axis using grow and shrink factors can affect cross axis, so remeasure affected items and lines.
+ for (var i = 0; i < _state.Lines.Count; i++)
+ {
+ var flexLine = _state.Lines[i];
+ var (itemsCount, freeU) = GetLineMeasureU(flexLine, max.U, spacing.U);
+ var (lineMult, autoMargins, remainingFreeU) = GetLineMultInfo(flexLine, freeU);
+
+ if (lineMult != 0.0 && remainingFreeU != 0.0)
+ {
+ double maxV = 0.0;
+ for (var j = flexLine.First; j <= flexLine.Last; j++)
+ {
+ var element = _visibleChildren[j];
+ var baseLength = Flex.GetBaseLength(element);
+ var mult = GetItemMult(element, freeU);
+ var length = Math.Max(0.0, baseLength + remainingFreeU * mult / lineMult);
+ element.Measure(Uv.ToSize(max.WithU(length), isColumn));
+
+ maxV = Math.Max(Uv.FromSize(element.DesiredSize, isColumn).V, maxV);
+ }
+
+ flexLine.V = maxV;
+ _state.Lines[i] = flexLine;
+ }
+ }
+
+ if (Wrap == FlexWrap.WrapReverse)
+ {
+ _state.Lines.Reverse();
+ }
+
+ var totalLineV = _state.Lines.Sum(l => l.V);
+ var panelSize = _state.Lines.Count == 0 ? default : new Uv(panelSizeU, totalLineV + totalSpacingV);
+ return Uv.ToSize(panelSize, isColumn);
+ }
+
+ ///
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ if (_visibleChildren is not { Length: > 0 } || _state.Lines.Count == 0)
+ {
+ return finalSize;
+ }
+
+ var isColumn = Direction is FlexDirection.Column or FlexDirection.ColumnReverse;
+ var isReverse = Direction is FlexDirection.RowReverse or FlexDirection.ColumnReverse;
+
+ var panelSize = Uv.FromSize(finalSize, isColumn);
+ var spacing = Uv.FromSize(ColumnSpacing, RowSpacing, isColumn);
+
+ var linesCount = _state.Lines.Count;
+ var totalLineV = _state.Lines.Sum(s => s.V);
+ var totalSpacingV = (linesCount - 1) * spacing.V;
+ var totalV = totalLineV + totalSpacingV;
+ var freeV = panelSize.V - totalV;
+
+ var alignContent = DetermineAlignContent(AlignContent, freeV, linesCount);
+
+ var (v, spacingV) = GetCrossAxisPosAndSpacing(alignContent, spacing, freeV, linesCount);
+
+ var scaleV = alignContent == FlexAlignContent.Stretch && totalLineV != 0 ? (panelSize.V - totalSpacingV) / totalLineV : 1.0;
+
+ foreach (var line in _state.Lines)
+ {
+ var lineV = scaleV * line.V;
+ var (itemsCount, freeU) = GetLineMeasureU(line, panelSize.U, spacing.U);
+ var (lineMult, lineAutoMargins, remainingFreeU) = GetLineMultInfo(line, freeU);
+
+ var currentFreeU = remainingFreeU;
+ if (lineMult != 0.0 && remainingFreeU != 0.0)
+ {
+ for (var i = line.First; i <= line.Last; i++)
+ {
+ var element = _visibleChildren[i];
+ var baseLength = Flex.GetBaseLength(element);
+ var mult = GetItemMult(element, freeU);
+ if (mult != 0.0)
+ {
+ var length = Math.Max(0.0, baseLength + remainingFreeU * mult / lineMult);
+ Flex.SetCurrentLength(element, length);
+ currentFreeU -= length - baseLength;
+ }
+ }
+ }
+ remainingFreeU = currentFreeU;
+
+ if (lineAutoMargins != 0 && remainingFreeU != 0.0)
+ {
+ for (var i = line.First; i <= line.Last; i++)
+ {
+ var element = _visibleChildren[i];
+ var baseLength = Flex.GetCurrentLength(element);
+ var autoMargins = GetItemAutoMargins(element, isColumn);
+ if (autoMargins != 0)
+ {
+ var length = Math.Max(0.0, baseLength + remainingFreeU * autoMargins / lineAutoMargins);
+ Flex.SetCurrentLength(element, length);
+ currentFreeU -= length - baseLength;
+ }
+ }
+ }
+ remainingFreeU = currentFreeU;
+
+ var (u, spacingU) = GetMainAxisPosAndSpacing(JustifyContent, line, spacing, remainingFreeU, itemsCount);
+
+ for (var i = line.First; i <= line.Last; i++)
+ {
+ var element = _visibleChildren[i];
+ var size = Uv.FromSize(element.DesiredSize, isColumn).WithU(Flex.GetCurrentLength(element));
+ var align = Flex.GetAlignSelf(element) ?? AlignItems;
+
+ var positionV = align switch
+ {
+ FlexAlignItems.FlexStart => v,
+ FlexAlignItems.FlexEnd => v + lineV - size.V,
+ FlexAlignItems.Center => v + (lineV - size.V) / 2,
+ FlexAlignItems.Stretch => v,
+ _ => throw new InvalidOperationException()
+ };
+
+ size = size.WithV(align == FlexAlignItems.Stretch ? lineV : size.V);
+ var position = new Uv(isReverse ? panelSize.U - size.U - u : u, positionV);
+ element.Arrange(new Rect(Uv.ToPoint(position, isColumn), Uv.ToSize(size, isColumn)));
+
+ u += size.U + spacingU;
+ }
+
+ v += lineV + spacingV;
+ }
+
+ return finalSize;
+ }
+
+ private static Uv MeasureChild(Layoutable element, Uv max, bool isColumn)
+ {
+ var basis = Flex.GetBasis(element);
+ var flexConstraint = basis.Kind switch
+ {
+ FlexBasisKind.Auto => max.U,
+ FlexBasisKind.Absolute => basis.Value,
+ FlexBasisKind.Relative => max.U * basis.Value / 100,
+ _ => throw new InvalidOperationException($"Unsupported FlexBasisKind value: {basis.Kind}")
+ };
+ element.Measure(Uv.ToSize(max.WithU(flexConstraint), isColumn));
+
+ var size = Uv.FromSize(element.DesiredSize, isColumn);
+
+ var flexLength = basis.Kind switch
+ {
+ FlexBasisKind.Auto => size.U,
+ FlexBasisKind.Absolute or FlexBasisKind.Relative => Math.Max(size.U, flexConstraint),
+ _ => throw new InvalidOperationException()
+ };
+ size = size.WithU(flexLength);
+
+ Flex.SetBaseLength(element, flexLength);
+ Flex.SetCurrentLength(element, flexLength);
+ return size;
+ }
+
+ private static FlexAlignContent DetermineAlignContent(FlexAlignContent currentAlignContent, double freeV, int linesCount)
+ {
+ // Determine AlignContent based on available space and line count
+ return currentAlignContent switch
+ {
+ // If there's free vertical space, handle distribution based on the content alignment
+ FlexAlignContent.Stretch when freeV > 0.0 => FlexAlignContent.Stretch,
+ FlexAlignContent.SpaceBetween when freeV > 0.0 && linesCount > 1 => FlexAlignContent.SpaceBetween,
+ FlexAlignContent.SpaceAround when freeV > 0.0 && linesCount > 0 => FlexAlignContent.SpaceAround,
+ FlexAlignContent.SpaceEvenly when freeV > 0.0 && linesCount > 0 => FlexAlignContent.SpaceEvenly,
+
+ // Default alignments when there's no free space or not enough lines
+ FlexAlignContent.Stretch => FlexAlignContent.FlexStart,
+ FlexAlignContent.SpaceBetween => FlexAlignContent.FlexStart,
+ FlexAlignContent.SpaceAround => FlexAlignContent.Center,
+ FlexAlignContent.SpaceEvenly => FlexAlignContent.Center,
+ FlexAlignContent.FlexStart or FlexAlignContent.Center or FlexAlignContent.FlexEnd => currentAlignContent,
+
+ _ => throw new InvalidOperationException($"Unsupported AlignContent value: {currentAlignContent}")
+ };
+ }
+
+ private static (double v, double spacingV) GetCrossAxisPosAndSpacing(FlexAlignContent alignContent, Uv spacing,
+ double freeV, int linesCount)
+ {
+ return alignContent switch
+ {
+ FlexAlignContent.FlexStart => (0.0, spacing.V),
+ FlexAlignContent.FlexEnd => (freeV, spacing.V),
+ FlexAlignContent.Center => (freeV / 2, spacing.V),
+ FlexAlignContent.Stretch => (0.0, spacing.V),
+
+ FlexAlignContent.SpaceBetween when linesCount > 1 => (0.0, spacing.V + freeV / (linesCount - 1)),
+ FlexAlignContent.SpaceBetween => (0.0, spacing.V),
+
+ FlexAlignContent.SpaceAround when linesCount > 0 => (freeV / linesCount / 2, spacing.V + freeV / linesCount),
+ FlexAlignContent.SpaceAround => (freeV / 2, spacing.V),
+
+ FlexAlignContent.SpaceEvenly => (freeV / (linesCount + 1), spacing.V + freeV / (linesCount + 1)),
+
+ _ => throw new InvalidOperationException($"Unsupported AlignContent value: {alignContent}")
+ };
+ }
+
+ private static (double u, double spacingU) GetMainAxisPosAndSpacing(FlexJustifyContent justifyContent, FlexLine line,
+ Uv spacing, double remainingFreeU, int itemsCount)
+ {
+ return line.Grow > 0 ? (0.0, spacing.U) : justifyContent switch
+ {
+ FlexJustifyContent.FlexStart => (0.0, spacing.U),
+ FlexJustifyContent.FlexEnd => (remainingFreeU, spacing.U),
+ FlexJustifyContent.Center => (remainingFreeU / 2, spacing.U),
+
+ FlexJustifyContent.SpaceBetween when itemsCount > 1 => (0.0, spacing.U + remainingFreeU / (itemsCount - 1)),
+ FlexJustifyContent.SpaceBetween => (0.0, spacing.U),
+
+ FlexJustifyContent.SpaceAround when itemsCount > 0 => (remainingFreeU / itemsCount / 2, spacing.U + remainingFreeU / itemsCount),
+ FlexJustifyContent.SpaceAround => (remainingFreeU / 2, spacing.U),
+
+ FlexJustifyContent.SpaceEvenly when itemsCount > 0 => (remainingFreeU / (itemsCount + 1), spacing.U + remainingFreeU / (itemsCount + 1)),
+ FlexJustifyContent.SpaceEvenly => (remainingFreeU / 2, spacing.U),
+
+ _ => throw new InvalidOperationException($"Unsupported JustifyContent value: {justifyContent}")
+ };
+ }
+
+ private static (int ItemsCount, double FreeU) GetLineMeasureU(
+ FlexLine line, double panelSizeU, double spacingU)
+ {
+ var itemsCount = line.Count;
+ var totalSpacingU = (itemsCount - 1) * spacingU;
+ var totalU = line.U + totalSpacingU;
+ var freeU = panelSizeU - totalU;
+ return (itemsCount, freeU);
+ }
+
+ private static (double LineMult, double LineAutoMargins, double RemainingFreeU) GetLineMultInfo(FlexLine line, double freeU)
+ {
+ var lineMult = freeU switch
+ {
+ < 0 => line.Shrink,
+ > 0 => line.Grow,
+ _ => 0.0,
+ };
+ // https://www.w3.org/TR/css-flexbox-1/#remaining-free-space
+ // Sum of flex factors less than 1 reduces remaining free space to be distributed.
+ return lineMult is > 0 and < 1
+ ? (lineMult, line.AutoMargins, freeU * lineMult)
+ : (lineMult, line.AutoMargins, freeU);
+ }
+
+ private static double GetItemMult(Layoutable element, double freeU)
+ {
+ var mult = freeU switch
+ {
+ < 0 => Flex.GetShrink(element),
+ > 0 => Flex.GetGrow(element),
+ _ => 0.0,
+ };
+ return mult;
+ }
+
+ private static int GetItemAutoMargins(Layoutable element, bool isColumn)
+ {
+ return isColumn
+ ? element.VerticalAlignment switch
+ {
+ VerticalAlignment.Stretch => 0,
+ VerticalAlignment.Top or VerticalAlignment.Bottom => 1,
+ VerticalAlignment.Center => 2,
+ _ => throw new InvalidOperationException()
+ }
+ : element.HorizontalAlignment switch
+ {
+ HorizontalAlignment.Stretch => 0,
+ HorizontalAlignment.Left or HorizontalAlignment.Right => 1,
+ HorizontalAlignment.Center => 2,
+ _ => throw new InvalidOperationException()
+ };
+ }
+
+ protected override void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ {
+ base.ChildrenChanged(sender, e);
+
+ if (e.OldItems is { } oldItems)
+ foreach (var old in oldItems)
+ {
+ if (old is Visual v)
+ if (_childVisibilitySubscriptions.Remove(v, out var disposable))
+ {
+ disposable.Dispose();
+ }
+ }
+
+ if (e.NewItems is { } newItems)
+ foreach (var newItem in newItems)
+ {
+ if (newItem is Visual visual)
+ {
+ _childVisibilitySubscriptions.Add(visual, visual.GetObservable(IsVisibleProperty).Subscribe(new AnonymousObserver(OnChildVisibilityChanged)));
+ }
+ }
+
+ UpdateVisibleChildren();
+ }
+
+ private void OnChildVisibilityChanged(bool isVisible)
+ {
+ UpdateVisibleChildren();
+ }
+
+ private void UpdateVisibleChildren()
+ {
+ _visibleChildren = Children.Where(s_isVisible).OrderBy(s_getOrder).ToArray();
+
+ InvalidateMeasure();
+ }
+
+ private readonly struct FlexLayoutState
+ {
+ public List Lines { get; } = new List();
+
+ public FlexLayoutState() { }
+ }
+
+ private struct LineData
+ {
+ public double U { get; set; }
+
+ public double V { get; set; }
+
+ public double Shrink { get; set; }
+
+ public double Grow { get; set; }
+
+ public int AutoMargins { get; set; }
+ }
+
+ private struct FlexLine
+ {
+ public FlexLine(int first, int last, LineData l)
+ {
+ First = first;
+ Last = last;
+ U = l.U;
+ V = l.V;
+ Shrink = l.Shrink;
+ Grow = l.Grow;
+ AutoMargins = l.AutoMargins;
+ }
+
+ /// First item index.
+ public int First { get; }
+
+ /// Last item index.
+ public int Last { get; }
+
+ /// Sum of main sizes of items.
+ public double U { get; }
+
+ /// Max of cross sizes of items.
+ public double V { get; set; }
+
+ /// Sum of shrink factors of flexible items.
+ public double Shrink { get; }
+
+ /// Sum of grow factors of flexible items.
+ public double Grow { get; }
+
+ /// Number of "auto margins" along main axis.
+ public int AutoMargins { get; }
+
+ /// Number of items.
+ public int Count => Last - First + 1;
+ }
+
+ private readonly struct Uv
+ {
+ public Uv(double u, double v)
+ {
+ U = u;
+ V = v;
+ }
+
+ public double U { get; }
+
+ public double V { get; }
+
+ public static Uv FromSize(double width, double height, bool swap) =>
+ new Uv(swap ? height : width, swap ? width : height);
+
+ public static Uv FromSize(Size size, bool swap) =>
+ FromSize(size.Width, size.Height, swap);
+
+ public static Point ToPoint(Uv uv, bool swap) =>
+ new Point(swap ? uv.V : uv.U, swap ? uv.U : uv.V);
+
+ public static Size ToSize(Uv uv, bool swap) =>
+ new Size(swap ? uv.V : uv.U, swap ? uv.U : uv.V);
+
+ public Uv WithU(double u) =>
+ new Uv(u, V);
+
+ public Uv WithV(double v) =>
+ new Uv(U, v);
+
+ public override string ToString() =>
+ $"U: {U}, V: {V}";
+ }
+ }
+}
diff --git a/src/Avalonia.Controls/FlexPanel/FlexWrap.cs b/src/Avalonia.Controls/FlexPanel/FlexWrap.cs
new file mode 100644
index 0000000000..826d7bf661
--- /dev/null
+++ b/src/Avalonia.Controls/FlexPanel/FlexWrap.cs
@@ -0,0 +1,26 @@
+namespace Avalonia.Controls
+{
+ ///
+ /// Describes the wrap behavior of the
+ ///
+ public enum FlexWrap
+ {
+ ///
+ /// The is single line.
+ ///
+ ///
+ /// This is the default value.
+ ///
+ NoWrap,
+
+ ///
+ /// The is multi line.
+ ///
+ Wrap,
+
+ ///
+ /// Same as but new lines are added in the opposite cross-axis direction.
+ ///
+ WrapReverse
+ }
+}
diff --git a/src/Avalonia.Controls/HotkeyManager.cs b/src/Avalonia.Controls/HotkeyManager.cs
index 584a56a135..06ff9cb18c 100644
--- a/src/Avalonia.Controls/HotkeyManager.cs
+++ b/src/Avalonia.Controls/HotkeyManager.cs
@@ -38,18 +38,8 @@ namespace Avalonia.Controls
public bool CanExecute(object? parameter)
{
- if (reference.Target is InputElement target)
+ if (reference.Target is { } target)
{
- var current = target as Visual;
- while (current != null && current is not TopLevel)
- {
- if (!current.IsVisible)
- {
- return false;
- }
- current = current.VisualParent;
- }
-
if (target is ICommandSource commandSource && commandSource.Command is { } command)
{
return commandSource.IsEffectivelyEnabled
diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs
index 5e8ee86c72..ef927b8267 100644
--- a/src/Avalonia.Controls/Image.cs
+++ b/src/Avalonia.Controls/Image.cs
@@ -1,3 +1,4 @@
+using System;
using Avalonia.Automation;
using Avalonia.Automation.Peers;
using Avalonia.Controls.Automation.Peers;
@@ -6,7 +7,7 @@ using Avalonia.Media.Imaging;
using Avalonia.Metadata;
namespace Avalonia.Controls
-{
+{
///
/// Displays a image.
///
@@ -17,7 +18,7 @@ namespace Avalonia.Controls
///
public static readonly StyledProperty SourceProperty =
AvaloniaProperty.Register(nameof(Source));
-
+
///
/// Defines the property.
///
@@ -38,6 +39,9 @@ namespace Avalonia.Controls
nameof(StretchDirection),
StretchDirection.Both);
+ private Rect _currentDrawingBounds;
+ private bool _subscribedToDrawingImageSource;
+
static Image()
{
AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty, BlendModeProperty);
@@ -84,7 +88,7 @@ namespace Avalonia.Controls
///
protected override bool BypassFlowDirectionPolicies => true;
-
+
///
/// Renders the control.
///
@@ -148,6 +152,62 @@ namespace Avalonia.Controls
}
}
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == SourceProperty)
+ {
+ _currentDrawingBounds = default;
+ if (change.OldValue is DrawingImage oldDrawingImage && _subscribedToDrawingImageSource)
+ {
+ _subscribedToDrawingImageSource = false;
+ oldDrawingImage.Invalidated -= OnSourceInvalidated;
+ }
+
+ if (change.NewValue is DrawingImage newDrawingImage && IsAttachedToVisualTree)
+ {
+ _subscribedToDrawingImageSource = true;
+ newDrawingImage.Invalidated += OnSourceInvalidated;
+ }
+ }
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+
+ if (!_subscribedToDrawingImageSource && Source is DrawingImage drawingImage)
+ {
+ _subscribedToDrawingImageSource = true;
+ drawingImage.Invalidated += OnSourceInvalidated;
+ }
+ }
+
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromVisualTree(e);
+
+ if (_subscribedToDrawingImageSource && Source is DrawingImage drawingImage)
+ {
+ _subscribedToDrawingImageSource = false;
+ drawingImage.Invalidated -= OnSourceInvalidated;
+ }
+ }
+
+ private void OnSourceInvalidated(object? sender, EventArgs e)
+ {
+ if (IsAttachedToVisualTree && Source is DrawingImage drawingImage && drawingImage.Drawing is { } drawing)
+ {
+ var bounds = drawing.GetBounds();
+ if (bounds != _currentDrawingBounds)
+ {
+ InvalidateMeasure();
+ }
+ _currentDrawingBounds = bounds;
+ }
+ }
+
protected override AutomationPeer OnCreateAutomationPeer()
{
return new ImageAutomationPeer(this);
diff --git a/src/Avalonia.Controls/InputPaneAwareBehavior.cs b/src/Avalonia.Controls/InputPaneAwareBehavior.cs
new file mode 100644
index 0000000000..19bff0ff11
--- /dev/null
+++ b/src/Avalonia.Controls/InputPaneAwareBehavior.cs
@@ -0,0 +1,23 @@
+namespace Avalonia.Controls
+{
+ ///
+ /// Specifies the behavior takes when input pane state changes.
+ ///
+ public enum InputPaneAwareBehavior
+ {
+ ///
+ /// The view doesn't resize or move the content when input pane state changes.
+ ///
+ None = 0,
+
+ ///
+ /// The view moves the content vertically when input pane states changes. The content is not resized.
+ ///
+ Pan,
+
+ ///
+ /// The view resizes the content when input pane state changes.
+ ///
+ Resize
+ }
+}
diff --git a/src/Avalonia.Controls/InputPaneAwareDecorator.cs b/src/Avalonia.Controls/InputPaneAwareDecorator.cs
new file mode 100644
index 0000000000..fdcb59b25f
--- /dev/null
+++ b/src/Avalonia.Controls/InputPaneAwareDecorator.cs
@@ -0,0 +1,142 @@
+using System.Diagnostics.CodeAnalysis;
+using Avalonia.Animation;
+using Avalonia.Animation.Easings;
+using Avalonia.Controls.Platform;
+
+namespace Avalonia.Controls
+{
+ ///
+ /// A control that automatically adjusts its child position or height based on the input pane's height to ensure the content is visible.
+ ///
+ public class InputPaneAwareDecorator : Decorator
+ {
+ private InputPaneAwareBehavior _behavior;
+ private IInputPane? _inputPane;
+ private bool _firstLayoutDone;
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty BehaviorProperty = AvaloniaProperty.RegisterDirect(
+ nameof(Behavior),
+ o => o.Behavior,
+ (o, x) => o.Behavior = x);
+
+ private static readonly StyledProperty CurrentInputPanePaddingProperty = AvaloniaProperty.Register(
+ nameof(CurrentInputPanePadding));
+
+ ///
+ /// Gets or sets how the view reacts to the input pane state.
+ ///
+ public InputPaneAwareBehavior Behavior
+ {
+ get => _behavior;
+ set => SetAndRaise(BehaviorProperty, ref _behavior, value);
+ }
+
+ private double CurrentInputPanePadding
+ {
+ get => GetValue(CurrentInputPanePaddingProperty);
+ set => SetValue(CurrentInputPanePaddingProperty, value);
+ }
+
+ static InputPaneAwareDecorator()
+ {
+ AffectsMeasure(BehaviorProperty, CurrentInputPanePaddingProperty);
+ AffectsArrange(CurrentInputPanePaddingProperty);
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ if (_inputPane != null && _firstLayoutDone && VisualRoot is { } root && Behavior == InputPaneAwareBehavior.Resize)
+ {
+ SetCurrentValue(PaddingProperty, new Thickness(0, 0, 0, CurrentInputPanePadding));
+ }
+ return base.MeasureOverride(availableSize);
+ }
+
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ _firstLayoutDone = true;
+
+ if (Behavior == InputPaneAwareBehavior.Pan)
+ {
+ Child?.Arrange(new Rect(new Point(0, -CurrentInputPanePadding), finalSize));
+
+ return finalSize;
+ }
+ else
+ return base.ArrangeOverride(finalSize);
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+
+ _inputPane = TopLevel.GetTopLevel(this)?.InputPane;
+ _inputPane?.StateChanged += InputPaneAwareView_StateChanged;
+ EnsureInputPanePaddingApplied();
+ }
+
+ [UnconditionalSuppressMessage("AvaloniaProperty", "AVP1012")]
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromVisualTree(e);
+ _inputPane?.StateChanged -= InputPaneAwareView_StateChanged;
+ _inputPane = null;
+ SetCurrentValue(PaddingProperty, default);
+ CurrentInputPanePadding = 0;
+ }
+
+ [UnconditionalSuppressMessage("AvaloniaProperty", "AVP1012")]
+ private void EnsureInputPanePaddingApplied()
+ {
+ SetCurrentValue(PaddingProperty, default);
+
+ if (_inputPane != null && _firstLayoutDone && this.VisualRoot is { } root && Behavior != InputPaneAwareBehavior.None)
+ {
+ var occludedRect = _inputPane.OccludedRect;
+
+ var transformMatrix = this.TransformToVisual(root) ?? Matrix.Identity;
+
+ var translatedRect = Bounds.TransformToAABB(transformMatrix);
+
+ var intersect = occludedRect.Intersect(translatedRect);
+ CurrentInputPanePadding = intersect.Height;
+ }
+ else
+ {
+ CurrentInputPanePadding = 0;
+ }
+ }
+
+ private void InputPaneAwareView_StateChanged(object? sender, InputPaneStateEventArgs e)
+ {
+ var transition = new DoubleTransition()
+ {
+ Property = CurrentInputPanePaddingProperty,
+ Duration = e.AnimationDuration,
+ Easing = e.Easing as Easing ?? new LinearEasing()
+ };
+
+ Transitions =
+ [
+ transition
+ ];
+
+ EnsureInputPanePaddingApplied();
+
+ InvalidateMeasure();
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if(change.Property == BehaviorProperty)
+ {
+ EnsureInputPanePaddingApplied();
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index a3900874a1..8b7a6ca06d 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -776,7 +776,7 @@ namespace Avalonia.Controls
LogicalChildren.RemoveAll(toRemove);
}
- private IDataTemplate? GetEffectiveItemTemplate()
+ private protected IDataTemplate? GetEffectiveItemTemplate()
{
if (ItemTemplate is { } itemTemplate)
return itemTemplate;
diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
index 183882ca50..0628e0c0b9 100644
--- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
@@ -364,6 +364,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the content to be displayed by the presenter.
///
+ [Content]
[DependsOn(nameof(ContentTemplate))]
public object? Content
{
diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs
index 93a30b06a3..234f47258d 100644
--- a/src/Avalonia.Controls/Primitives/PopupRoot.cs
+++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs
@@ -126,6 +126,7 @@ namespace Avalonia.Controls.Primitives
public void Dispose()
{
PlatformImpl?.Dispose();
+ EnsureClosed();
}
private void UpdatePosition()
diff --git a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs
index d323965c13..cafd812941 100644
--- a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs
+++ b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs
@@ -312,6 +312,7 @@ namespace Avalonia.Controls
///
public void RequestRefresh()
{
+ RefreshInfoProvider?.InteractionRatio = 1;
RefreshVisualizerState = RefreshVisualizerState.Refreshing;
RefreshInfoProvider?.OnRefreshStarted();
@@ -320,8 +321,8 @@ namespace Avalonia.Controls
private void RefreshCompleted()
{
+ RefreshInfoProvider?.InteractionRatio = 0;
RefreshVisualizerState = RefreshVisualizerState.Idle;
-
RefreshInfoProvider?.OnRefreshCompleted();
}
diff --git a/src/Avalonia.Controls/SelectableTextBlock.cs b/src/Avalonia.Controls/SelectableTextBlock.cs
index a218eb0356..3c522f6f69 100644
--- a/src/Avalonia.Controls/SelectableTextBlock.cs
+++ b/src/Avalonia.Controls/SelectableTextBlock.cs
@@ -7,6 +7,7 @@ using Avalonia.Controls.Utils;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Interactivity;
+using Avalonia.Logging;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
using Avalonia.Utilities;
@@ -135,8 +136,18 @@ namespace Avalonia.Controls
{
var clipboard = TopLevel.GetTopLevel(this)?.Clipboard;
- if (clipboard != null)
+ if (clipboard is null)
+ return;
+
+ try
+ {
await clipboard.SetTextAsync(text);
+ }
+ catch (Exception ex) when (ClipboardHelper.IsExpectedClipboardException(ex))
+ {
+ Logger.TryGet(LogEventLevel.Warning, LogArea.Control)
+ ?.Log(this, "Failed to write text to clipboard: {Error}", ex);
+ }
}
}
diff --git a/src/Avalonia.Controls/StackPanel.cs b/src/Avalonia.Controls/StackPanel.cs
index 007a35c077..63984592da 100644
--- a/src/Avalonia.Controls/StackPanel.cs
+++ b/src/Avalonia.Controls/StackPanel.cs
@@ -261,6 +261,9 @@ namespace Avalonia.Controls
// Get next child.
var child = children[i];
+ // Measure the child.
+ child.Measure(layoutSlotSize);
+
bool isVisible = child.IsVisible;
if (isVisible && !hasVisibleChild)
@@ -268,8 +271,6 @@ namespace Avalonia.Controls
hasVisibleChild = true;
}
- // Measure the child.
- child.Measure(layoutSlotSize);
Size childDesiredSize = child.DesiredSize;
// Accumulate child size.
diff --git a/src/Avalonia.Controls/TableView.cs b/src/Avalonia.Controls/TableView.cs
index 87141677f0..6fbc634478 100644
--- a/src/Avalonia.Controls/TableView.cs
+++ b/src/Avalonia.Controls/TableView.cs
@@ -5,6 +5,7 @@ using Avalonia.Collections;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Data;
+using Avalonia.LogicalTree;
using Avalonia.Metadata;
using static Avalonia.Controls.Presenters.TableViewLayoutHelper;
@@ -139,6 +140,7 @@ public class TableView : ListBox
}
column.TableView = this;
+ ((ISetLogicalParent)column).SetParent(this);
}
private void DetachColumn(TableViewColumn column)
@@ -146,6 +148,7 @@ public class TableView : ListBox
Debug.Assert(column.TableView == this || column.TableView is null);
column.TableView = null;
+ ((ISetLogicalParent)column).SetParent(null);
column.ActualWidth = double.NaN;
}
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 0126d62f27..40cf617d0a 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -1308,7 +1308,17 @@ namespace Avalonia.Controls
if (clipboard == null)
return;
- await clipboard.SetTextAsync(text);
+ try
+ {
+ await clipboard.SetTextAsync(text);
+ }
+ catch (Exception ex) when (ClipboardHelper.IsExpectedClipboardException(ex))
+ {
+ Logger.TryGet(LogEventLevel.Warning, LogArea.Control)
+ ?.Log(this, "Failed to write text to clipboard: {Error}", ex);
+ return;
+ }
+
DeleteSelection();
}
}
@@ -1330,15 +1340,17 @@ namespace Avalonia.Controls
if (!eventArgs.Handled)
{
var clipboard = TopLevel.GetTopLevel(this)?.Clipboard;
+ if (clipboard is null)
+ return;
try
{
- if (clipboard != null)
- await clipboard.SetTextAsync(text);
+ await clipboard.SetTextAsync(text);
}
- catch (UnauthorizedAccessException uex)
+ catch (Exception ex) when (ClipboardHelper.IsExpectedClipboardException(ex))
{
- Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, "Failed to write text to clipboard: {Error}", uex);
+ Logger.TryGet(LogEventLevel.Warning, LogArea.Control)
+ ?.Log(this, "Failed to write text to clipboard: {Error}", ex);
}
}
}
@@ -1365,13 +1377,10 @@ namespace Avalonia.Controls
{
text = await clipboard.TryGetTextAsync();
}
- catch (TimeoutException)
- {
- // Silently ignore.
- }
- catch (UnauthorizedAccessException uex)
+ catch (Exception ex) when (ClipboardHelper.IsExpectedClipboardException(ex))
{
- Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, "Failed to read text from clipboard: {Error}", uex);
+ Logger.TryGet(LogEventLevel.Warning, LogArea.Control)
+ ?.Log(this, "Failed to read text from clipboard: {Error}", ex);
}
}
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index eeb6ae3488..2fd1524cef 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -42,7 +42,8 @@ namespace Avalonia.Controls
public abstract class TopLevel : ContentControl,
ICloseable,
IStyleHost,
- ILogicalRoot
+ ILogicalRoot,
+ IThemeVariantRoot
{
///
/// Defines the property.
@@ -122,6 +123,7 @@ namespace Avalonia.Controls
private readonly IDisposable? _backGestureSubscription;
private readonly Dictionary _platformImplBindings = new();
private double _scaling;
+ private bool _isClosed;
private Size _clientSize;
private Size? _frameSize;
private WindowTransparencyLevel _actualTransparencyLevel;
@@ -232,7 +234,7 @@ namespace Avalonia.Controls
- impl.Closed = HandleClosed;
+ impl.Closed = EnsureClosed;
impl.Paint = HandlePaint;
impl.Resized = HandleResized;
impl.ScalingChanged += HandleScalingChanged;
@@ -248,19 +250,19 @@ namespace Avalonia.Controls
_globalStyles.GlobalStylesAdded += ((IStyleHost)this).StylesAdded;
_globalStyles.GlobalStylesRemoved += ((IStyleHost)this).StylesRemoved;
}
+
if (_applicationThemeHost is { })
{
SetValue(ActualThemeVariantProperty, _applicationThemeHost.ActualThemeVariant, BindingPriority.Template);
_applicationThemeHost.ActualThemeVariantChanged += GlobalActualThemeVariantChanged;
}
+ else
+ {
+ ThemeVariant.UpdateActualThemeVariant(this);
+ }
+
CreatePlatformImplBinding(ActualThemeVariantProperty, variant =>
{
- if(_applicationThemeHost is AvaloniaObject element)
- {
- if (element.GetValue(ThemeVariantScope.RequestedThemeVariantProperty) is { } requestedThemeVariant)
- variant = requestedThemeVariant == ThemeVariant.Default ? ThemeVariant.Default : variant;
- }
- variant ??= ThemeVariant.Default;
PlatformImpl?.SetFrameThemeVariant((PlatformThemeVariant?)variant);
});
@@ -400,6 +402,8 @@ namespace Avalonia.Controls
set => SetValue(RequestedThemeVariantProperty, value);
}
+ bool IThemeVariantRoot.IsThemeVariantRoot => _applicationThemeHost is null;
+
///
/// Occurs when physical Back Button is pressed or a back navigation has been requested.
///
@@ -658,6 +662,18 @@ namespace Avalonia.Controls
private protected void StopRendering() => MediaContext.Instance.RemoveTopLevel(this);
+ ///
+ /// Runs the top level teardown exactly once, no matter whether it was initiated by the
+ /// platform via or by a managed Dispose().
+ ///
+ private protected void EnsureClosed()
+ {
+ if (_isClosed)
+ return;
+ _isClosed = true;
+ HandleClosed();
+ }
+
///
/// Handles a closed notification from .
///
diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs
index 8c6a17a429..d51e72dc3b 100644
--- a/src/Avalonia.Controls/TreeViewItem.cs
+++ b/src/Avalonia.Controls/TreeViewItem.cs
@@ -198,7 +198,7 @@ namespace Avalonia.Controls
if (m.HasValue)
{
- var bounds = new Rect(_header.Bounds.Size);
+ var bounds = new Rect(GetHeaderTargetSize(_header));
var rect = bounds.TransformToAABB(m.Value);
e.TargetRect = rect;
}
@@ -206,6 +206,17 @@ namespace Avalonia.Controls
}
}
+ private static Size GetHeaderTargetSize(Control header)
+ {
+ // Use the DesiredWidth, not Bounds.Width: the latter is stretched to the full width of the tree view's extent,
+ // preventing scrolling, whereas the desired size is what the header actually needs.
+ var margin = header.Margin;
+ var desiredWidth = header.DesiredSize.Width - margin.Left - margin.Right;
+ var boundsSize = header.Bounds.Size;
+
+ return boundsSize.WithWidth(Math.Clamp(desiredWidth, 0.0, boundsSize.Width));
+ }
+
///
protected override void OnKeyDown(KeyEventArgs e)
{
diff --git a/src/Avalonia.Controls/Utils/ClipboardHelper.cs b/src/Avalonia.Controls/Utils/ClipboardHelper.cs
new file mode 100644
index 0000000000..60da32be7f
--- /dev/null
+++ b/src/Avalonia.Controls/Utils/ClipboardHelper.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.Controls.Utils;
+
+internal static class ClipboardHelper
+{
+ public static bool IsExpectedClipboardException(Exception exception)
+ => exception is TimeoutException
+ or OperationCanceledException
+ or UnauthorizedAccessException
+ or COMException;
+}
diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs
index b21a04c1d4..dd575c01ec 100644
--- a/src/Avalonia.Controls/Viewbox.cs
+++ b/src/Avalonia.Controls/Viewbox.cs
@@ -113,6 +113,15 @@ namespace Avalonia.Controls
InvalidateMeasure();
}
+ else if (change.Property == TemplatedParentProperty)
+ {
+ // Update _containerVisual.TemplateParent, otherwise its descendants aren't reachable
+ // during the template's teardown and incorrectly stay attached to the visual tree.
+ if (change.NewValue is AvaloniaObject templatedParent)
+ {
+ _containerVisual.TemplatedParent = templatedParent;
+ }
+ }
}
///
diff --git a/src/Avalonia.Controls/VirtualizingStackPanel.cs b/src/Avalonia.Controls/VirtualizingStackPanel.cs
index d46d65ac4c..63e46b4c1b 100644
--- a/src/Avalonia.Controls/VirtualizingStackPanel.cs
+++ b/src/Avalonia.Controls/VirtualizingStackPanel.cs
@@ -293,10 +293,28 @@ namespace Avalonia.Controls
// Ensure that the focused element is in the correct position.
if (_focusedElement is not null && _focusedIndex >= 0)
{
+ var realizedEndU = u;
+ var sizeU = orientation == Orientation.Horizontal ?
+ _focusedElement.DesiredSize.Width :
+ _focusedElement.DesiredSize.Height;
+
u = GetOrEstimateElementU(_focusedIndex);
+
+ // The focused element's position is estimated as it's outside the realized
+ // range. A bad estimate must not place it over the realized elements in the
+ // viewport: an element before the realized range always ends at or before its
+ // start, and one after it always starts at or after its end.
+ if (_realizedElements.Count > 0 && !double.IsNaN(_realizedElements.StartU))
+ {
+ if (_focusedIndex < _realizedElements.FirstIndex)
+ u = Math.Min(u, _realizedElements.StartU - sizeU);
+ else if (_focusedIndex > _realizedElements.LastIndex)
+ u = Math.Max(u, realizedEndU);
+ }
+
var rect = orientation == Orientation.Horizontal ?
- new Rect(u, 0, _focusedElement.DesiredSize.Width, finalSize.Height) :
- new Rect(0, u, finalSize.Width, _focusedElement.DesiredSize.Height);
+ new Rect(u, 0, sizeU, finalSize.Height) :
+ new Rect(0, u, finalSize.Width, sizeU);
_focusedElement.Arrange(rect);
}
@@ -818,6 +836,18 @@ namespace Avalonia.Controls
return;
}
+ var horizontal = Orientation == Orientation.Horizontal;
+ var viewportEnd = horizontal ? _viewport.Right : _viewport.Bottom;
+
+ if (!_hasReachedEnd && MathUtilities.GreaterThanOrClose(
+ viewportEnd,
+ horizontal ? Bounds.Width : Bounds.Height))
+ {
+ index = itemCount - 1;
+ position = viewportEnd - EstimateElementSizeU();
+ return;
+ }
+
// If we have realised elements and a valid StartU then try to use this information to
// get the anchor element.
if (_realizedElements?.StartU is { } u && !double.IsNaN(u))
@@ -915,6 +945,9 @@ namespace Avalonia.Controls
var index = viewport.anchorIndex;
var horizontal = Orientation == Orientation.Horizontal;
var u = viewport.anchorU;
+ var viewportEnd = horizontal ? _viewport.Right : _viewport.Bottom;
+ var anchorAtEnd = !_hasReachedEnd && index == items.Count - 1 &&
+ MathUtilities.GreaterThanOrClose(viewportEnd, horizontal ? Bounds.Width : Bounds.Height);
// Reset boundary flags
_hasReachedStart = false;
@@ -937,6 +970,12 @@ namespace Avalonia.Controls
var sizeU = horizontal ? e.DesiredSize.Width : e.DesiredSize.Height;
var sizeV = horizontal ? e.DesiredSize.Height : e.DesiredSize.Width;
+ if (anchorAtEnd && index == viewport.anchorIndex)
+ {
+ u = viewportEnd - sizeU;
+ viewport.anchorU = u;
+ }
+
_measureElements!.Add(index, e, u, sizeU);
viewport.measuredV = Math.Max(viewport.measuredV, sizeV);
diff --git a/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs b/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
index f6d620a534..2cc25a9dde 100644
--- a/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
+++ b/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
@@ -1,8 +1,6 @@
-using System;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Avalonia.Media;
using Avalonia.Platform;
-using Avalonia.Threading;
using Tmds.DBus.Protocol;
using Avalonia.FreeDesktop.DBus;
@@ -12,12 +10,14 @@ namespace Avalonia.FreeDesktop
{
private readonly Settings? _settings;
- private PlatformColorValues? _lastColorValues;
+ private PlatformColorValues _colorValues;
private PlatformThemeVariant? _themeVariant;
private Color? _accentColor;
public DBusPlatformSettings()
{
+ _colorValues = base.GetColorValues();
+
if (DBusHelper.DefaultConnection is not { } conn)
return;
@@ -26,7 +26,7 @@ namespace Avalonia.FreeDesktop
_ = TryGetInitialValuesAsync();
}
- public override PlatformColorValues GetColorValues() => _lastColorValues ?? base.GetColorValues();
+ public override PlatformColorValues GetColorValues() => _colorValues;
private async Task TryGetInitialValuesAsync()
{
@@ -34,17 +34,10 @@ namespace Avalonia.FreeDesktop
{
_themeVariant = await TryGetThemeVariantAsync(settings);
_accentColor = await TryGetAccentColorAsync(settings);
- _lastColorValues = BuildPlatformColorValues();
- if (_lastColorValues is not null)
- Dispatcher.UIThread.Post(() => OnColorValuesChanged(_lastColorValues));
+ UpdateColorValues();
}
}
- internal void OnRequestDefaultThemeVariant()
- {
- _ = TryGetInitialValuesAsync();
- }
-
private static async Task TryGetThemeVariantAsync(Settings settings)
{
try
@@ -82,32 +75,48 @@ namespace Avalonia.FreeDesktop
}
}
+ private void UpdateColorValues()
+ {
+ var oldColorValues = _colorValues;
+ var colorValues = BuildPlatformColorValues(_themeVariant, _accentColor);
+
+ if (oldColorValues != colorValues)
+ {
+ _colorValues = colorValues;
+ OnColorValuesChanged(colorValues);
+ }
+ }
+
private void SettingsChangedHandler((string Namespace, string Key, VariantValue Value) tuple)
{
switch (tuple)
{
case ("org.freedesktop.appearance", "color-scheme", var colorScheme):
_themeVariant = ToColorScheme(colorScheme.GetUInt32());
- _lastColorValues = BuildPlatformColorValues();
- OnColorValuesChanged(_lastColorValues!);
+ UpdateColorValues();
break;
case ("org.freedesktop.appearance", "accent-color", var accentColor):
_accentColor = ToAccentColor(accentColor);
- _lastColorValues = BuildPlatformColorValues();
- OnColorValuesChanged(_lastColorValues!);
+ UpdateColorValues();
break;
}
}
- private PlatformColorValues? BuildPlatformColorValues()
+ private static PlatformColorValues BuildPlatformColorValues(
+ PlatformThemeVariant? nullableThemeVariant,
+ Color? nullableAccentColor)
{
- if (_themeVariant is { } themeVariant && _accentColor is { } accentColor)
- return new PlatformColorValues { ThemeVariant = themeVariant, AccentColor1 = accentColor };
- if (_themeVariant is { } themeVariant1)
- return new PlatformColorValues { ThemeVariant = themeVariant1 };
- if (_accentColor is { } accentColor1)
- return new PlatformColorValues { AccentColor1 = accentColor1 };
- return null;
+ return (nullableThemeVariant, nullableAccentColor) switch
+ {
+ ({ } themeVariant, { } accentColor)
+ => new PlatformColorValues { ThemeVariant = themeVariant, AccentColor1 = accentColor },
+ ({ } themeVariant, null)
+ => new PlatformColorValues { ThemeVariant = themeVariant },
+ (null, { } accentColor)
+ => new PlatformColorValues { AccentColor1 = accentColor },
+ (null, null)
+ => new PlatformColorValues { ThemeVariant = PlatformThemeVariant.Light }
+ };
}
private static PlatformThemeVariant ToColorScheme(uint value)
diff --git a/src/Avalonia.Native/NativePlatformSettings.cs b/src/Avalonia.Native/NativePlatformSettings.cs
index b95d9a9439..0b8b76b69b 100644
--- a/src/Avalonia.Native/NativePlatformSettings.cs
+++ b/src/Avalonia.Native/NativePlatformSettings.cs
@@ -8,14 +8,20 @@ namespace Avalonia.Native;
internal class NativePlatformSettings : DefaultPlatformSettings
{
private readonly IAvnPlatformSettings _platformSettings;
+ private PlatformColorValues? _colorValues;
+ private string? _lastLanguage;
public NativePlatformSettings(IAvnPlatformSettings platformSettings)
{
_platformSettings = platformSettings;
platformSettings.RegisterColorsChange(new ColorsChangeCallback(this));
+ platformSettings.RegisterLanguageChange(new LanguageChangeCallback(this));
}
public override PlatformColorValues GetColorValues()
+ => _colorValues ??= GetUncachedColorValues();
+
+ private PlatformColorValues GetUncachedColorValues()
{
var (theme, contrast) = _platformSettings.PlatformTheme switch
{
@@ -48,7 +54,34 @@ internal class NativePlatformSettings : DefaultPlatformSettings
public void OnColorValuesChanged()
{
- OnColorValuesChanged(GetColorValues());
+ var oldColorValues = _colorValues;
+ var colorValues = GetUncachedColorValues();
+
+ if (oldColorValues != colorValues)
+ {
+ _colorValues = colorValues;
+ OnColorValuesChanged(colorValues);
+ }
+ }
+
+ public override string PreferredApplicationLanguage =>
+ _lastLanguage ??= QueryPreferredApplicationLanguage();
+
+ private void OnPreferredLanguageChanged()
+ {
+ var oldLanguage = _lastLanguage;
+ _lastLanguage = null;
+
+ if (oldLanguage != PreferredApplicationLanguage)
+ {
+ OnPreferredApplicationLanguageChanged();
+ }
+ }
+
+ private string QueryPreferredApplicationLanguage()
+ {
+ using var language = _platformSettings.PreferredLanguage;
+ return language?.String is { Length: > 0 } value ? value : base.PreferredApplicationLanguage;
}
private class ColorsChangeCallback : NativeCallbackBase, IAvnActionCallback
@@ -65,4 +98,19 @@ internal class NativePlatformSettings : DefaultPlatformSettings
_settings.OnColorValuesChanged();
}
}
+
+ private class LanguageChangeCallback : NativeCallbackBase, IAvnActionCallback
+ {
+ private readonly NativePlatformSettings _settings;
+
+ public LanguageChangeCallback(NativePlatformSettings settings)
+ {
+ _settings = settings;
+ }
+
+ public void Run()
+ {
+ _settings.OnPreferredLanguageChanged();
+ }
+ }
}
diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs
index 4c5652c03e..1f7f478788 100644
--- a/src/Avalonia.Native/WindowImplBase.cs
+++ b/src/Avalonia.Native/WindowImplBase.cs
@@ -51,11 +51,23 @@ namespace Avalonia.Native
base.Init(handle);
+ int defaultWidth = 0, defaultHeight = 0;
+
var monitor = this.TryGetFeature()!.AllScreens
.OrderBy(x => x.Scaling)
- .First(m => m.Bounds.Contains(Position));
+ .FirstOrDefault(m => m.Bounds.Contains(Position));
+
+ if (monitor != null)
+ {
+ // Emulate Windows 7+ default window size behavior.
+ defaultWidth = (int)(monitor.WorkingArea.Width * 0.75d);
+ defaultHeight = (int)(monitor.WorkingArea.Height * 0.7d);
+ }
+
+ defaultWidth = Math.Max(defaultWidth, 300);
+ defaultHeight = Math.Max(defaultHeight, 200);
- Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), WindowResizeReason.Layout);
+ Resize(new Size(defaultWidth, defaultHeight), WindowResizeReason.Layout);
}
public void Activate()
@@ -71,12 +83,6 @@ namespace Avalonia.Native
public override void SetFrameThemeVariant(PlatformThemeVariant? themeVariant)
{
var settings = AvaloniaLocator.Current.GetService();
-
- if (themeVariant is null && settings is NativePlatformSettings typedSettings)
- {
- typedSettings.OnColorValuesChanged();
- }
-
themeVariant ??= settings?.GetColorValues().ThemeVariant ?? PlatformThemeVariant.Light;
Native?.SetFrameThemeVariant((AvnPlatformThemeVariant)themeVariant);
}
diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl
index 91a252c020..ee46a46f8c 100644
--- a/src/Avalonia.Native/avn.idl
+++ b/src/Avalonia.Native/avn.idl
@@ -1367,6 +1367,8 @@ interface IAvnPlatformSettings : IUnknown
AvnPlatformThemeVariant GetPlatformTheme();
uint GetAccentColor();
void RegisterColorsChange(IAvnActionCallback* callback);
+ HRESULT GetPreferredLanguage(IAvnString** ret);
+ void RegisterLanguageChange(IAvnActionCallback* callback);
}
[uuid(12edf00d-5803-4d3f-9947-b4840e5e9372)]
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml
index 2248551a95..778ea5b002 100644
--- a/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml
@@ -416,6 +416,7 @@
20
12
+ 12
SemiBold
@@ -1262,6 +1263,7 @@
20
12
+ 12
SemiBold
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
index 2718733419..dbc36efd85 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
@@ -133,7 +133,9 @@
SelectedDate="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedDate, Mode=TwoWay}"
DisplayDate="{TemplateBinding DisplayDate}"
DisplayDateStart="{TemplateBinding DisplayDateStart}"
- DisplayDateEnd="{TemplateBinding DisplayDateEnd}" />
+ DisplayDateEnd="{TemplateBinding DisplayDateEnd}"
+ IsWeekNumberVisible="{TemplateBinding IsWeekNumberVisible}"
+ WeekNumberRule="{TemplateBinding WeekNumberRule}" />
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
index ac3ebadbb8..58f8a2b150 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
@@ -10,7 +10,8 @@
x:ClassModifier="internal">
-
+
@@ -75,8 +76,14 @@
basically...MinWidth of DayItem = 40, 40 * 7 = 280 + margins/padding = ~294
Viewport height is set from # of rows displayed (2-8) in Month mode, = ~290 for 6 weeks (+ day names)
-->
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -136,6 +175,7 @@
Background="{TemplateBinding BorderBrush}"
MinHeight="290"
Grid.Row="1"
+ Grid.ColumnSpan="2"
IsVisible="False">
@@ -159,5 +199,15 @@
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
index b38187cd60..52c63f8e22 100644
--- a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
@@ -133,6 +133,10 @@
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/WindowDrawnDecorations.xaml b/src/Avalonia.Themes.Fluent/Controls/WindowDrawnDecorations.xaml
index d9af9faf79..2c4969f212 100644
--- a/src/Avalonia.Themes.Fluent/Controls/WindowDrawnDecorations.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/WindowDrawnDecorations.xaml
@@ -128,7 +128,8 @@
VerticalAlignment="Top"
Background="{DynamicResource SystemControlBackgroundChromeMediumLowBrush}"
WindowDecorationProperties.ElementRole="TitleBar">
-
@@ -196,7 +197,8 @@
-
+
@@ -209,6 +211,18 @@
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -176,5 +204,16 @@
+
+
+
+
diff --git a/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml b/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
index d933afa43e..45d895541d 100644
--- a/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
@@ -158,6 +158,10 @@
+
+
+
+
-
+
@@ -215,6 +217,18 @@
+
+
+
+