Public Access
77 lines
4.2 KiB
C#
77 lines
4.2 KiB
C#
using Avalonia;
|
|
using Avalonia.Headless;
|
|
using Avalonia.Media;
|
|
using DodoSSH.Client.App.Layout.Tests;
|
|
|
|
[assembly: AvaloniaTestApplication(typeof(HeadlessApp))]
|
|
|
|
namespace DodoSSH.Client.App.Layout.Tests;
|
|
|
|
/// <summary>
|
|
/// Builds the real application for a headless renderer.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// <see cref="DodoSshApp"/> itself, not a stand-in, because the thing being measured is how the shipped
|
|
/// styles lay out — a harness with its own theme would measure a window nobody sees. Its
|
|
/// <c>OnFrameworkInitializationCompleted</c> only composes the object graph when the lifetime is a classic
|
|
/// desktop one, and a headless session's is not, so loading it here brings the Fluent theme and the dark
|
|
/// variant and starts no vault, no listener and no browser.
|
|
/// </para>
|
|
/// <para>
|
|
/// Skia rather than the headless drawing stub, which is the one deliberate cost in this file. The stub's
|
|
/// font manager returns invented glyph metrics, and text height is an input to every stacked panel in this
|
|
/// window — measuring against it would produce numbers that are self-consistent and unrelated to the
|
|
/// application. With Skia and the same Inter font the application registers, a measured height is the
|
|
/// height a user gets.
|
|
/// </para>
|
|
/// </remarks>
|
|
internal static class HeadlessApp
|
|
{
|
|
/// <summary>Found by name; <see cref="AvaloniaTestApplicationAttribute"/> is the contract.</summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// The default family is named explicitly, because the paragraph above was describing an intention
|
|
/// rather than what happened. <c>WithInterFont</c> registers a font collection; it does not make it
|
|
/// the default. Avalonia resolves that from the platform — which is to say from whatever the machine
|
|
/// has installed — so a suite whose whole job is measuring text was measuring Segoe UI on a
|
|
/// developer's Windows and DejaVu on their Linux, and treating the two numbers as one.
|
|
/// </para>
|
|
/// <para>
|
|
/// On a machine with no fonts at all it does not merely differ, it stops: <c>FontManager</c> throws
|
|
/// "Default font family name can't be null or empty" during <c>AppBuilder.SetupUnsafe</c>, before any
|
|
/// test body runs. That is how a container CI runner reports all sixty-eight of these as failures with
|
|
/// not one assertion among them. Naming a font costs the runner nothing, because it travels inside the
|
|
/// package rather than on the host — true of Inter before this and of Montserrat now.
|
|
/// </para>
|
|
/// </remarks>
|
|
public static AppBuilder BuildAvaloniaApp() =>
|
|
AppBuilder.Configure<DodoSshApp>()
|
|
.UseSkia()
|
|
.UseHeadless(new AvaloniaHeadlessPlatformOptions { UseHeadlessDrawing = false })
|
|
.WithInterFont()
|
|
.With(new FontManagerOptions
|
|
{
|
|
DefaultFamilyName = DefaultFamily,
|
|
FontFallbacks = [new FontFallback { FontFamily = new FontFamily(InterFamily) }],
|
|
});
|
|
|
|
/// <summary>The family <c>Program.BuildAvaloniaApp</c> asks the font manager to default to.</summary>
|
|
/// <remarks>
|
|
/// Kept in step with <c>Program.BuildAvaloniaApp</c> by hand, and it matters that they agree: a
|
|
/// harness pinning a different default from the one the application runs with would certify heights
|
|
/// for a window nobody sees, which is the failure the opening paragraph of this file is about. It was
|
|
/// Inter until the v3 design; now it is Montserrat, embedded the same way, and Inter moves down to
|
|
/// <see cref="InterFamily"/> as the fallback both <c>BuildAvaloniaApp</c> methods name it as.
|
|
/// </remarks>
|
|
internal const string DefaultFamily = "avares://DodoSSH.Client.Shell/Assets/Fonts#Montserrat";
|
|
|
|
/// <summary>The family <c>WithInterFont</c> registers.</summary>
|
|
/// <remarks>
|
|
/// No longer the default — see <see cref="DefaultFamily"/> — but still registered and still named
|
|
/// here, because it is still the fallback both heads' <c>BuildAvaloniaApp</c> fall back to, and a test
|
|
/// measuring a glyph Montserrat does not cover has to fall back to the same font the application does.
|
|
/// </remarks>
|
|
internal const string InterFamily = "avares://Avalonia.Fonts.Inter/Assets#Inter";
|
|
}
|