committed by
GitHub
363 changed files with 5391 additions and 7278 deletions
@ -1 +1,2 @@ |
|||||
|
github: avaloniaui |
||||
open_collective: avalonia |
open_collective: avalonia |
||||
|
|||||
@ -0,0 +1,5 @@ |
|||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<PropertyGroup> |
||||
|
<EnableNETAnalyzers>true</EnableNETAnalyzers> |
||||
|
</PropertyGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Avalonia; |
||||
|
using Avalonia.Web.Blazor; |
||||
|
|
||||
|
namespace ControlCatalog.Blazor.Web; |
||||
|
|
||||
|
public partial class App |
||||
|
{ |
||||
|
protected override void OnParametersSet() |
||||
|
{ |
||||
|
AppBuilder.Configure<ControlCatalog.App>() |
||||
|
.UseBlazor() |
||||
|
// .With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
|
||||
|
.SetupWithSingleViewLifetime(); |
||||
|
|
||||
|
base.OnParametersSet(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> |
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net7.0</TargetFramework> |
||||
|
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<EmccTotalMemory>16777216</EmccTotalMemory> |
||||
|
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport> |
||||
|
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-rc.1.22427.2" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-rc.1.22427.2" PrivateAssets="all" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj" /> |
||||
|
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
||||
|
<Import Project="..\..\build\BuildTargets.targets" /> |
||||
|
|
||||
|
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.props" /> |
||||
|
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.targets" /> |
||||
|
|
||||
|
</Project> |
||||
|
|
||||
@ -0,0 +1,29 @@ |
|||||
|
using System; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using ControlCatalog.Blazor.Web; |
||||
|
|
||||
|
public class Program |
||||
|
{ |
||||
|
public static async Task Main(string[] args) |
||||
|
{ |
||||
|
await CreateHostBuilder(args).Build().RunAsync(); |
||||
|
} |
||||
|
|
||||
|
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args) |
||||
|
{ |
||||
|
var builder = WebAssemblyHostBuilder.CreateDefault(args); |
||||
|
|
||||
|
builder.RootComponents.Add<App>("#app"); |
||||
|
|
||||
|
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); |
||||
|
|
||||
|
return builder; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
@ -1,20 +0,0 @@ |
|||||
using Avalonia; |
|
||||
using Avalonia.Web.Blazor; |
|
||||
|
|
||||
namespace ControlCatalog.Web; |
|
||||
|
|
||||
public partial class App |
|
||||
{ |
|
||||
protected override void OnParametersSet() |
|
||||
{ |
|
||||
WebAppBuilder.Configure<ControlCatalog.App>() |
|
||||
.AfterSetup(_ => |
|
||||
{ |
|
||||
ControlCatalog.Pages.EmbedSample.Implementation = new EmbedSampleWeb(); |
|
||||
}) |
|
||||
.With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
|
|
||||
.SetupWithSingleViewLifetime(); |
|
||||
|
|
||||
base.OnParametersSet(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +1,42 @@ |
|||||
using System; |
using System; |
||||
|
using System.Runtime.InteropServices.JavaScript; |
||||
using Avalonia; |
|
||||
using Avalonia.Platform; |
using Avalonia.Platform; |
||||
using Avalonia.Web.Blazor; |
using Avalonia.Web; |
||||
|
|
||||
using ControlCatalog.Pages; |
using ControlCatalog.Pages; |
||||
|
|
||||
using Microsoft.JSInterop; |
|
||||
|
|
||||
namespace ControlCatalog.Web; |
namespace ControlCatalog.Web; |
||||
|
|
||||
public class EmbedSampleWeb : INativeDemoControl |
public class EmbedSampleWeb : INativeDemoControl |
||||
{ |
{ |
||||
public IPlatformHandle CreateControl(bool isSecond, IPlatformHandle parent, Func<IPlatformHandle> createDefault) |
public IPlatformHandle CreateControl(bool isSecond, IPlatformHandle parent, Func<IPlatformHandle> createDefault) |
||||
{ |
{ |
||||
var runtime = AvaloniaLocator.Current.GetRequiredService<IJSInProcessRuntime>(); |
|
||||
|
|
||||
if (isSecond) |
if (isSecond) |
||||
{ |
{ |
||||
var iframe = runtime.Invoke<IJSInProcessObjectReference>("document.createElement", "iframe"); |
var iframe = EmbedInterop.CreateElement("iframe"); |
||||
iframe.InvokeVoid("setAttribute", "src", "https://www.youtube.com/embed/kZCIporjJ70"); |
iframe.SetProperty("src", "https://www.youtube.com/embed/kZCIporjJ70"); |
||||
|
|
||||
return new JSObjectControlHandle(iframe); |
return new JSObjectControlHandle(iframe); |
||||
} |
} |
||||
else |
else |
||||
{ |
{ |
||||
// window.createAppButton source is defined in "app.js" file.
|
var defaultHandle = (JSObjectControlHandle)createDefault(); |
||||
var button = runtime.Invoke<IJSInProcessObjectReference>("window.createAppButton"); |
|
||||
|
_ = JSHost.ImportAsync("embed.js", "./embed.js").ContinueWith(_ => |
||||
|
{ |
||||
|
EmbedInterop.AddAppButton(defaultHandle.Object); |
||||
|
}); |
||||
|
|
||||
return new JSObjectControlHandle(button); |
return defaultHandle; |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
internal static partial class EmbedInterop |
||||
|
{ |
||||
|
[JSImport("globalThis.document.createElement")] |
||||
|
public static partial JSObject CreateElement(string tagName); |
||||
|
|
||||
|
[JSImport("addAppButton", "embed.js")] |
||||
|
public static partial void AddAppButton(JSObject parentObject); |
||||
|
} |
||||
|
|||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,7 @@ |
|||||
|
<linker> |
||||
|
<assembly fullname="ControlCatalog" preserve="All" /> |
||||
|
<assembly fullname="ControlCatalog.Web" preserve="All" /> |
||||
|
<assembly fullname="Avalonia.Themes.Fluent" preserve="All" /> |
||||
|
<assembly fullname="Avalonia.Themes.Simple" preserve="All" /> |
||||
|
<assembly fullname="Avalonia.Controls.ColorPicker" preserve="All" /> |
||||
|
</linker> |
||||
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
@ -1,105 +0,0 @@ |
|||||
using Android.OS; |
|
||||
using AndroidX.AppCompat.App; |
|
||||
using Android.Content.Res; |
|
||||
using AndroidX.Lifecycle; |
|
||||
using Avalonia.Controls.ApplicationLifetimes; |
|
||||
using Avalonia.Controls; |
|
||||
using Android.Runtime; |
|
||||
using Android.App; |
|
||||
using Android.Content; |
|
||||
using System; |
|
||||
|
|
||||
namespace Avalonia.Android |
|
||||
{ |
|
||||
public abstract class AvaloniaActivity : AppCompatActivity |
|
||||
{ |
|
||||
internal class SingleViewLifetime : ISingleViewApplicationLifetime |
|
||||
{ |
|
||||
public AvaloniaView View { get; internal set; } |
|
||||
|
|
||||
public Control MainView |
|
||||
{ |
|
||||
get => (Control)View.Content; |
|
||||
set => View.Content = value; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
internal Action<int, Result, Intent> ActivityResult; |
|
||||
internal AvaloniaView View; |
|
||||
internal AvaloniaViewModel _viewModel; |
|
||||
|
|
||||
protected abstract AppBuilder CreateAppBuilder(); |
|
||||
|
|
||||
protected override void OnCreate(Bundle savedInstanceState) |
|
||||
{ |
|
||||
var builder = CreateAppBuilder(); |
|
||||
|
|
||||
|
|
||||
var lifetime = new SingleViewLifetime(); |
|
||||
|
|
||||
builder.AfterSetup(x => |
|
||||
{ |
|
||||
_viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel; |
|
||||
|
|
||||
View = new AvaloniaView(this); |
|
||||
if (_viewModel.Content != null) |
|
||||
{ |
|
||||
View.Content = _viewModel.Content; |
|
||||
} |
|
||||
|
|
||||
SetContentView(View); |
|
||||
lifetime.View = View; |
|
||||
|
|
||||
View.Prepare(); |
|
||||
}); |
|
||||
|
|
||||
builder.SetupWithLifetime(lifetime); |
|
||||
|
|
||||
base.OnCreate(savedInstanceState); |
|
||||
} |
|
||||
public object Content |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return _viewModel.Content; |
|
||||
} |
|
||||
set |
|
||||
{ |
|
||||
_viewModel.Content = value; |
|
||||
if (View != null) |
|
||||
View.Content = value; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public override void OnConfigurationChanged(Configuration newConfig) |
|
||||
{ |
|
||||
base.OnConfigurationChanged(newConfig); |
|
||||
} |
|
||||
|
|
||||
protected override void OnDestroy() |
|
||||
{ |
|
||||
View.Content = null; |
|
||||
|
|
||||
base.OnDestroy(); |
|
||||
} |
|
||||
|
|
||||
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data) |
|
||||
{ |
|
||||
base.OnActivityResult(requestCode, resultCode, data); |
|
||||
|
|
||||
ActivityResult?.Invoke(requestCode, resultCode, data); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public abstract class AvaloniaActivity<TApp> : AvaloniaActivity where TApp : Application, new() |
|
||||
{ |
|
||||
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid(); |
|
||||
|
|
||||
protected override AppBuilder CreateAppBuilder() |
|
||||
{ |
|
||||
var builder = AppBuilder.Configure<TApp>(); |
|
||||
|
|
||||
return CustomizeAppBuilder(builder); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,70 @@ |
|||||
|
using System; |
||||
|
using Android.App; |
||||
|
using Android.Content; |
||||
|
using Android.Content.Res; |
||||
|
using Android.OS; |
||||
|
using Android.Runtime; |
||||
|
using AndroidX.AppCompat.App; |
||||
|
using AndroidX.Lifecycle; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
public abstract class AvaloniaMainActivity : AppCompatActivity, IActivityResultHandler |
||||
|
{ |
||||
|
internal static object ViewContent; |
||||
|
|
||||
|
public Action<int, Result, Intent> ActivityResult { get; set; } |
||||
|
internal AvaloniaView View; |
||||
|
|
||||
|
protected override void OnCreate(Bundle savedInstanceState) |
||||
|
{ |
||||
|
View = new AvaloniaView(this); |
||||
|
if (ViewContent != null) |
||||
|
{ |
||||
|
View.Content = ViewContent; |
||||
|
} |
||||
|
|
||||
|
if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime) |
||||
|
{ |
||||
|
lifetime.View = View; |
||||
|
} |
||||
|
|
||||
|
base.OnCreate(savedInstanceState); |
||||
|
|
||||
|
SetContentView(View); |
||||
|
} |
||||
|
|
||||
|
public object Content |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return ViewContent; |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
ViewContent = value; |
||||
|
if (View != null) |
||||
|
View.Content = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void OnConfigurationChanged(Configuration newConfig) |
||||
|
{ |
||||
|
base.OnConfigurationChanged(newConfig); |
||||
|
} |
||||
|
|
||||
|
protected override void OnDestroy() |
||||
|
{ |
||||
|
View.Content = null; |
||||
|
|
||||
|
base.OnDestroy(); |
||||
|
} |
||||
|
|
||||
|
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data) |
||||
|
{ |
||||
|
base.OnActivityResult(requestCode, resultCode, data); |
||||
|
|
||||
|
ActivityResult?.Invoke(requestCode, resultCode, data); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using Android.OS; |
||||
|
using AndroidX.AppCompat.App; |
||||
|
using AndroidX.Lifecycle; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
public abstract class AvaloniaSplashActivity : AppCompatActivity |
||||
|
{ |
||||
|
protected abstract AppBuilder CreateAppBuilder(); |
||||
|
|
||||
|
protected override void OnCreate(Bundle? savedInstanceState) |
||||
|
{ |
||||
|
base.OnCreate(savedInstanceState); |
||||
|
|
||||
|
var builder = CreateAppBuilder(); |
||||
|
|
||||
|
var lifetime = new SingleViewLifetime(); |
||||
|
|
||||
|
builder.SetupWithLifetime(lifetime); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public abstract class AvaloniaSplashActivity<TApp> : AvaloniaSplashActivity where TApp : Application, new() |
||||
|
{ |
||||
|
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid(); |
||||
|
|
||||
|
protected override AppBuilder CreateAppBuilder() |
||||
|
{ |
||||
|
var builder = AppBuilder.Configure<TApp>(); |
||||
|
|
||||
|
return CustomizeAppBuilder(builder); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,11 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace Avalonia.Android |
|
||||
{ |
|
||||
internal class AvaloniaViewModel : AndroidX.Lifecycle.ViewModel |
|
||||
{ |
|
||||
public object Content { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,11 @@ |
|||||
|
using System; |
||||
|
using Android.App; |
||||
|
using Android.Content; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
public interface IActivityResultHandler |
||||
|
{ |
||||
|
public Action<int, Result, Intent> ActivityResult { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.ApplicationLifetimes; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
internal class SingleViewLifetime : ISingleViewApplicationLifetime |
||||
|
{ |
||||
|
private AvaloniaView _view; |
||||
|
|
||||
|
public AvaloniaView View |
||||
|
{ |
||||
|
get => _view; internal set |
||||
|
{ |
||||
|
if (_view != null) |
||||
|
{ |
||||
|
_view.Content = null; |
||||
|
_view.Dispose(); |
||||
|
} |
||||
|
_view = value; |
||||
|
_view.Content = MainView; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Control MainView { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The font metrics is holding information about a font's ascent, descent, etc. in design em units.
|
||||
|
/// </summary>
|
||||
|
public readonly struct FontMetrics |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the font design units per em.
|
||||
|
/// </summary>
|
||||
|
public short DesignEmHeight { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A <see cref="bool"/> value indicating whether all glyphs in the font have the same advancement.
|
||||
|
/// </summary>
|
||||
|
public bool IsFixedPitch { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the recommended distance above the baseline in design em size.
|
||||
|
/// </summary>
|
||||
|
public int Ascent { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the recommended distance under the baseline in design em size.
|
||||
|
/// </summary>
|
||||
|
public int Descent { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the recommended additional space between two lines of text in design em size.
|
||||
|
/// </summary>
|
||||
|
public int LineGap { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the recommended line spacing of a formed text line.
|
||||
|
/// </summary>
|
||||
|
public int LineSpacing => Descent - Ascent + LineGap; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value that indicates the distance of the underline from the baseline in design em size.
|
||||
|
/// </summary>
|
||||
|
public int UnderlinePosition { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value that indicates the thickness of the underline in design em size.
|
||||
|
/// </summary>
|
||||
|
public int UnderlineThickness { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value that indicates the distance of the strikethrough from the baseline in design em size.
|
||||
|
/// </summary>
|
||||
|
public int StrikethroughPosition { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value that indicates the thickness of the underline in design em size.
|
||||
|
/// </summary>
|
||||
|
public int StrikethroughThickness { get; init; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Specifies algorithmic style simulations to be applied to the typeface.
|
||||
|
/// Bold and oblique simulations can be combined via bitwise OR operation.
|
||||
|
/// </summary>
|
||||
|
[Flags] |
||||
|
public enum FontSimulations : byte |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// No simulations are performed.
|
||||
|
/// </summary>
|
||||
|
None = 0x0000, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Algorithmic emboldening is performed.
|
||||
|
/// </summary>
|
||||
|
Bold = 0x0001, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Algorithmic italicization is performed.
|
||||
|
/// </summary>
|
||||
|
Oblique = 0x0002 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
namespace Avalonia.Media; |
||||
|
|
||||
|
public readonly struct GlyphMetrics |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Distance from the x-origin to the left extremum of the glyph.
|
||||
|
/// </summary>
|
||||
|
public int XBearing { get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Distance from the top extremum of the glyph to the y-origin.
|
||||
|
/// </summary>
|
||||
|
public int YBearing{ get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Distance from the left extremum of the glyph to the right extremum.
|
||||
|
/// </summary>
|
||||
|
public int Width{ get; init; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Distance from the top extremum of the glyph to the bottom extremum.
|
||||
|
/// </summary>
|
||||
|
public int Height{ get; init; } |
||||
|
} |
||||
@ -1,125 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Media |
|
||||
{ |
|
||||
public sealed class GlyphTypeface : IDisposable |
|
||||
{ |
|
||||
public GlyphTypeface(Typeface typeface) |
|
||||
: this(FontManager.Current.PlatformImpl.CreateGlyphTypeface(typeface)) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public GlyphTypeface(IGlyphTypefaceImpl platformImpl) |
|
||||
{ |
|
||||
PlatformImpl = platformImpl; |
|
||||
} |
|
||||
|
|
||||
public IGlyphTypefaceImpl PlatformImpl { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the font design units per em.
|
|
||||
/// </summary>
|
|
||||
public short DesignEmHeight => PlatformImpl.DesignEmHeight; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the recommended distance above the baseline in design em size.
|
|
||||
/// </summary>
|
|
||||
public int Ascent => PlatformImpl.Ascent; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the recommended distance under the baseline in design em size.
|
|
||||
/// </summary>
|
|
||||
public int Descent => PlatformImpl.Descent; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the recommended additional space between two lines of text in design em size.
|
|
||||
/// </summary>
|
|
||||
public int LineGap => PlatformImpl.LineGap; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the recommended line height.
|
|
||||
/// </summary>
|
|
||||
public int LineHeight => Descent - Ascent + LineGap; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value that indicates the distance of the underline from the baseline in design em size.
|
|
||||
/// </summary>
|
|
||||
public int UnderlinePosition => PlatformImpl.UnderlinePosition; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value that indicates the thickness of the underline in design em size.
|
|
||||
/// </summary>
|
|
||||
public int UnderlineThickness => PlatformImpl.UnderlineThickness; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value that indicates the distance of the strikethrough from the baseline in design em size.
|
|
||||
/// </summary>
|
|
||||
public int StrikethroughPosition => PlatformImpl.StrikethroughPosition; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value that indicates the thickness of the underline in design em size.
|
|
||||
/// </summary>
|
|
||||
public int StrikethroughThickness => PlatformImpl.StrikethroughThickness; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// A <see cref="bool"/> value indicating whether all glyphs in the font have the same advancement.
|
|
||||
/// </summary>
|
|
||||
public bool IsFixedPitch => PlatformImpl.IsFixedPitch; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns an glyph index for the specified codepoint.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// Returns a replacement glyph if a glyph isn't found.
|
|
||||
/// </remarks>
|
|
||||
/// <param name="codepoint">The codepoint.</param>
|
|
||||
/// <returns>
|
|
||||
/// A glyph index.
|
|
||||
/// </returns>
|
|
||||
public ushort GetGlyph(uint codepoint) => PlatformImpl.GetGlyph(codepoint); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Tries to get an glyph index for specified codepoint.
|
|
||||
/// </summary>
|
|
||||
/// <param name="codepoint">The codepoint.</param>
|
|
||||
/// <param name="glyph">A glyph index.</param>
|
|
||||
/// <returns>
|
|
||||
/// <c>true</c> if an glyph index was found, <c>false</c> otherwise.
|
|
||||
/// </returns>
|
|
||||
public bool TryGetGlyph(uint codepoint, out ushort glyph) |
|
||||
{ |
|
||||
glyph = PlatformImpl.GetGlyph(codepoint); |
|
||||
|
|
||||
return glyph != 0; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns an array of glyph indices. Codepoints that are not represented by the font are returned as <code>0</code>.
|
|
||||
/// </summary>
|
|
||||
/// <param name="codepoints">The codepoints to map.</param>
|
|
||||
/// <returns></returns>
|
|
||||
public ushort[] GetGlyphs(ReadOnlySpan<uint> codepoints) => PlatformImpl.GetGlyphs(codepoints); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns the glyph advance for the specified glyph.
|
|
||||
/// </summary>
|
|
||||
/// <param name="glyph">The glyph.</param>
|
|
||||
/// <returns>
|
|
||||
/// The advance.
|
|
||||
/// </returns>
|
|
||||
public int GetGlyphAdvance(ushort glyph) => PlatformImpl.GetGlyphAdvance(glyph); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns an array of glyph advances in design em size.
|
|
||||
/// </summary>
|
|
||||
/// <param name="glyphs">The glyph indices.</param>
|
|
||||
/// <returns></returns>
|
|
||||
public int[] GetGlyphAdvances(ReadOnlySpan<ushort> glyphs) => PlatformImpl.GetGlyphAdvances(glyphs); |
|
||||
|
|
||||
void IDisposable.Dispose() |
|
||||
{ |
|
||||
PlatformImpl?.Dispose(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,33 +1,33 @@ |
|||||
namespace Avalonia.Media.TextFormatting |
namespace Avalonia.Media.TextFormatting |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// A metric that holds information about font specific measurements.
|
/// A metric that holds information about text specific measurements.
|
||||
/// </summary>
|
/// </summary>
|
||||
public readonly struct FontMetrics |
public readonly struct TextMetrics |
||||
{ |
{ |
||||
public FontMetrics(Typeface typeface, double fontRenderingEmSize) |
public TextMetrics(Typeface typeface, double fontRenderingEmSize) |
||||
{ |
{ |
||||
var glyphTypeface = typeface.GlyphTypeface; |
var fontMetrics = typeface.GlyphTypeface.Metrics; |
||||
|
|
||||
var scale = fontRenderingEmSize / glyphTypeface.DesignEmHeight; |
var scale = fontRenderingEmSize / fontMetrics.DesignEmHeight; |
||||
|
|
||||
FontRenderingEmSize = fontRenderingEmSize; |
FontRenderingEmSize = fontRenderingEmSize; |
||||
|
|
||||
Ascent = glyphTypeface.Ascent * scale; |
Ascent = fontMetrics.Ascent * scale; |
||||
|
|
||||
Descent = glyphTypeface.Descent * scale; |
Descent = fontMetrics.Descent * scale; |
||||
|
|
||||
LineGap = glyphTypeface.LineGap * scale; |
LineGap = fontMetrics.LineGap * scale; |
||||
|
|
||||
LineHeight = Descent - Ascent + LineGap; |
LineHeight = Descent - Ascent + LineGap; |
||||
|
|
||||
UnderlineThickness = glyphTypeface.UnderlineThickness * scale; |
UnderlineThickness = fontMetrics.UnderlineThickness * scale; |
||||
|
|
||||
UnderlinePosition = glyphTypeface.UnderlinePosition * scale; |
UnderlinePosition = fontMetrics.UnderlinePosition * scale; |
||||
|
|
||||
StrikethroughThickness = glyphTypeface.StrikethroughThickness * scale; |
StrikethroughThickness = fontMetrics.StrikethroughThickness * scale; |
||||
|
|
||||
StrikethroughPosition = glyphTypeface.StrikethroughPosition * scale; |
StrikethroughPosition = fontMetrics.StrikethroughPosition * scale; |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
@ -0,0 +1,22 @@ |
|||||
|
using System; |
||||
|
using System.Drawing; |
||||
|
|
||||
|
namespace Avalonia.Platform |
||||
|
{ |
||||
|
public interface IGlyphRunBuffer |
||||
|
{ |
||||
|
Span<ushort> GlyphIndices { get; } |
||||
|
|
||||
|
IGlyphRunImpl Build(); |
||||
|
} |
||||
|
|
||||
|
public interface IHorizontalGlyphRunBuffer : IGlyphRunBuffer |
||||
|
{ |
||||
|
Span<float> GlyphPositions { get; } |
||||
|
} |
||||
|
|
||||
|
public interface IPositionedGlyphRunBuffer : IGlyphRunBuffer |
||||
|
{ |
||||
|
Span<PointF> GlyphPositions { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
|
||||
|
namespace Avalonia.Utilities |
||||
|
{ |
||||
|
public static class SpanHelpers |
||||
|
{ |
||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
|
public static bool TryParseUInt(this ReadOnlySpan<char> span, NumberStyles style, IFormatProvider provider, out uint value) |
||||
|
{ |
||||
|
#if NETSTANDARD2_0
|
||||
|
return uint.TryParse(span.ToString(), style, provider, out value); |
||||
|
#else
|
||||
|
return uint.TryParse(span, style, provider, out value); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
|
public static bool TryParseInt(this ReadOnlySpan<char> span, out int value) |
||||
|
{ |
||||
|
#if NETSTANDARD2_0
|
||||
|
return int.TryParse(span.ToString(), out value); |
||||
|
#else
|
||||
|
return int.TryParse(span, out value); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
|
public static bool TryParseDouble(this ReadOnlySpan<char> span, NumberStyles style, IFormatProvider provider, out double value) |
||||
|
{ |
||||
|
#if NETSTANDARD2_0
|
||||
|
return double.TryParse(span.ToString(), style, provider, out value); |
||||
|
#else
|
||||
|
return double.TryParse(span, style, provider, out value); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
||||
|
public static bool TryParseByte(this ReadOnlySpan<char> span, NumberStyles style, IFormatProvider provider, out byte value) |
||||
|
{ |
||||
|
#if NETSTANDARD2_0
|
||||
|
return byte.TryParse(span.ToString(), style, provider, out value); |
||||
|
#else
|
||||
|
return byte.TryParse(span, style, provider, out value); |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue