diff --git a/src/Avalonia.Controls/AppBuilder.cs b/src/Avalonia.Controls/AppBuilder.cs
index 9259be8594..bc299bdbe1 100644
--- a/src/Avalonia.Controls/AppBuilder.cs
+++ b/src/Avalonia.Controls/AppBuilder.cs
@@ -60,6 +60,16 @@ namespace Avalonia
///
public string? RenderingSubsystemName { get; private set; }
+ ///
+ /// Gets or sets a method to call the initialize the text shaping subsystem.
+ ///
+ public Action? TextShapingSubsystemInitializer { get; private set; }
+
+ ///
+ /// Gets the name of the currently selected text shaping subsystem.
+ ///
+ public string? TextShapingSubsystemName { get; private set; }
+
///
/// Gets a method to call after the is setup.
///
@@ -224,6 +234,19 @@ namespace Avalonia
RenderingSubsystemName = name;
return Self;
}
+
+ ///
+ /// Specifies a text shaping subsystem to use.
+ ///
+ /// The method to call to initialize the text shaping subsystem.
+ /// The name of the text shaping subsystem.
+ /// An instance.
+ public AppBuilder UseTextShapingSubsystem(Action initializer, string name = "")
+ {
+ TextShapingSubsystemInitializer = initializer;
+ TextShapingSubsystemName = name;
+ return Self;
+ }
///
/// Specifies a runtime platform subsystem to use.
@@ -308,7 +331,12 @@ namespace Avalonia
if (RenderingSubsystemInitializer == null)
{
- throw new InvalidOperationException("No rendering system configured.");
+ throw new InvalidOperationException("No rendering system configured. Consider calling UseSkia().");
+ }
+
+ if (TextShapingSubsystemInitializer == null)
+ {
+ throw new InvalidOperationException("No text shaping system configured. Consider calling UseHarfBuzz().");
}
if (_appFactory == null)
@@ -333,6 +361,7 @@ namespace Avalonia
{
_optionsInitializers?.Invoke();
RuntimePlatformServicesInitializer?.Invoke();
+ TextShapingSubsystemInitializer?.Invoke();
RenderingSubsystemInitializer?.Invoke();
WindowingSubsystemInitializer?.Invoke();
AfterPlatformServicesSetupCallback?.Invoke(Self);
diff --git a/src/HarfBuzz/Avalonia.HarfBuzz/HarfBuzzApplicationExtensions.cs b/src/HarfBuzz/Avalonia.HarfBuzz/HarfBuzzApplicationExtensions.cs
index 508c9ef525..e07ae82627 100644
--- a/src/HarfBuzz/Avalonia.HarfBuzz/HarfBuzzApplicationExtensions.cs
+++ b/src/HarfBuzz/Avalonia.HarfBuzz/HarfBuzzApplicationExtensions.cs
@@ -20,7 +20,9 @@ namespace Avalonia
/// The configured instance.
public static AppBuilder UseHarfBuzz(this AppBuilder builder)
{
- return builder.With(new HarfBuzzTextShaper());
+ return builder.UseTextShapingSubsystem(
+ () => AvaloniaLocator.CurrentMutable.Bind().ToConstant(new HarfBuzzTextShaper()),
+ "HarfBuzz");
}
}
diff --git a/src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs b/src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
index 667a8ba3ee..48c5f5d84e 100644
--- a/src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
+++ b/src/Headless/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
@@ -121,7 +121,8 @@ namespace Avalonia.Headless
builder = builder.UseRenderingSubsystem(HeadlessPlatformRenderInterface.Initialize, "Headless");
return builder
.UseStandardRuntimePlatformSubsystem()
- .UseWindowingSubsystem(() => AvaloniaHeadlessPlatform.Initialize(opts), "Headless");
+ .UseWindowingSubsystem(() => AvaloniaHeadlessPlatform.Initialize(opts), "Headless")
+ .UseHarfBuzz();
}
}
}
diff --git a/src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs b/src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs
index 0e5a6b0c8b..cda9c4ae75 100644
--- a/src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs
+++ b/src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs
@@ -236,9 +236,12 @@ public sealed class HeadlessUnitTestSession : IDisposable, IAsyncDisposable
// If windowing subsystem wasn't initialized by user, force headless with default parameters.
if (appBuilder.WindowingSubsystemName != "Headless")
{
- appBuilder = appBuilder
- .UseHeadless(new AvaloniaHeadlessPlatformOptions())
- .UseHarfBuzz();
+ appBuilder = appBuilder.UseHeadless(new AvaloniaHeadlessPlatformOptions());
+ }
+
+ if (appBuilder.TextShapingSubsystemInitializer is null)
+ {
+ appBuilder = appBuilder.UseHarfBuzz();
}
// ReSharper disable once AccessToModifiedClosure
diff --git a/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj b/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj
index 797265af46..2732b6d549 100644
--- a/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj
+++ b/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj
@@ -9,6 +9,7 @@
+
diff --git a/tests/Avalonia.IntegrationTests.Win32/Infrastructure/AppManager.cs b/tests/Avalonia.IntegrationTests.Win32/Infrastructure/AppManager.cs
index 8ac5cc24ed..cba1a8ad73 100644
--- a/tests/Avalonia.IntegrationTests.Win32/Infrastructure/AppManager.cs
+++ b/tests/Avalonia.IntegrationTests.Win32/Infrastructure/AppManager.cs
@@ -24,6 +24,7 @@ internal static class AppManager
.Configure()
.UseWin32()
.UseSkia()
+ .UseHarfBuzz()
.SetupWithoutStarting();
appBuilder.Instance!.Styles.Add(new FluentTheme());