Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Avalonia.sln
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE
src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
src\Shared\StringCompatibilityExtensions.cs = src\Shared\StringCompatibilityExtensions.cs
src\Shared\StreamCompatibilityExtensions.cs = src\Shared\StreamCompatibilityExtensions.cs
src\Shared\StringCompatibilityExtensions.cs = src\Shared\StringCompatibilityExtensions.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
Expand Down Expand Up @@ -92,6 +92,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject
build\AnalyzerProject.targets = build\AnalyzerProject.targets
build\AvaloniaPublicKey.props = build\AvaloniaPublicKey.props
build\Base.props = build\Base.props
build\Binding.props = build\Binding.props
Expand Down Expand Up @@ -122,7 +123,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
build\WarnAsErrors.props = build\WarnAsErrors.props
build\XUnit.props = build\XUnit.props
build\AnalyzerProject.targets = build\AnalyzerProject.targets
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"
Expand Down Expand Up @@ -302,6 +302,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.MacCatalyst"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.tvOS", "samples\ControlCatalog.tvOS\ControlCatalog.tvOS.csproj", "{14342787-B4EF-4076-8C91-BA6C523DE8DF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HarfBuzz", "HarfBuzz", "{7670D720-6E84-4AFC-8331-A5C399481905}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.HarfBuzz", "src\HarfBuzz\Avalonia.HarfBuzz\Avalonia.HarfBuzz.csproj", "{E2BFA463-6402-4EF8-8945-FD9A10A914D1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -704,6 +708,10 @@ Global
{14342787-B4EF-4076-8C91-BA6C523DE8DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14342787-B4EF-4076-8C91-BA6C523DE8DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14342787-B4EF-4076-8C91-BA6C523DE8DF}.Release|Any CPU.Build.0 = Release|Any CPU
{E2BFA463-6402-4EF8-8945-FD9A10A914D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2BFA463-6402-4EF8-8945-FD9A10A914D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2BFA463-6402-4EF8-8945-FD9A10A914D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2BFA463-6402-4EF8-8945-FD9A10A914D1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -793,6 +801,7 @@ Global
{255614F5-CB64-4ECA-A026-E0B1AF6A2EF4} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{DE3C28DD-B602-4750-831D-345102A54CA0} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{14342787-B4EF-4076-8C91-BA6C523DE8DF} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{E2BFA463-6402-4EF8-8945-FD9A10A914D1} = {7670D720-6E84-4AFC-8331-A5C399481905}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
Expand Down
366 changes: 354 additions & 12 deletions api/Avalonia.nupkg.xml

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions samples/RenderDemo/Pages/CustomSkiaPage.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using Avalonia;
using Avalonia.Controls;
Expand All @@ -9,7 +8,6 @@
using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia;
using Avalonia.Threading;
using Avalonia.Utilities;
using SkiaSharp;

namespace RenderDemo.Pages
Expand All @@ -21,7 +19,7 @@ public CustomSkiaPage()
{
ClipToBounds = true;
var text = "Current rendering API is not Skia";
var glyphs = text.Select(ch => Typeface.Default.GlyphTypeface.GetGlyph(ch)).ToArray();
var glyphs = text.Select(ch => Typeface.Default.GlyphTypeface.CharacterToGlyphMap[ch]).ToArray();
_noSkia = new GlyphRun(Typeface.Default.GlyphTypeface, 12, text.AsMemory(), glyphs);
}

Expand Down
4 changes: 2 additions & 2 deletions samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public override void Render(DrawingContext context)

_fontSize += _direction;

_glyphIndices[0] = _glyphTypeface.GetGlyph(c);
_glyphIndices[0] = _glyphTypeface.CharacterToGlyphMap[c];

_characters[0] = c;

Expand Down Expand Up @@ -128,7 +128,7 @@ public override void Render(DrawingContext context)

_fontSize += _direction;

_glyphIndices[0] = _glyphTypeface.GetGlyph(c);
_glyphIndices[0] = _glyphTypeface.CharacterToGlyphMap[c];

_characters[0] = c;

Expand Down
1 change: 1 addition & 0 deletions src/Android/Avalonia.Android/AndroidPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public static AppBuilder UseAndroid(this AppBuilder builder)
return builder
.UseAndroidRuntimePlatformSubsystem()
.UseWindowingSubsystem(() => AndroidPlatform.Initialize(), "Android")
.UseHarfBuzz()
.UseSkia();
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Android/Avalonia.Android/Avalonia.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\..\Harfbuzz\Avalonia.Harfbuzz\Avalonia.Harfbuzz.csproj" />
<ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
</ItemGroup>

Expand Down
11 changes: 8 additions & 3 deletions src/Avalonia.Base/Media/FontManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fon
{
typeface = new Typeface(fallback.FontFamily, fontStyle, fontWeight, fontStretch);

if (TryGetGlyphTypeface(typeface, out var glyphTypeface) && glyphTypeface.TryGetGlyph((uint)codepoint, out _))
if (TryGetGlyphTypeface(typeface, out var glyphTypeface) && glyphTypeface.CharacterToGlyphMap.TryGetValue(codepoint, out _))
{
return true;
}
Expand All @@ -289,6 +289,11 @@ public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fon
if (TryGetFontCollection(source, out var fontCollection) &&
fontCollection.TryMatchCharacter(codepoint, fontStyle, fontWeight, fontStretch, familyName, culture, out typeface))
{
if (typeface.FontFamily.Name == DefaultFontFamily.Name && i + 1 < compositeKey.Keys.Count)
{
continue;
}

return true;
}
}
Expand All @@ -306,8 +311,8 @@ public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fon
}
}

//Try to find a match with the system font manager
return PlatformImpl.TryMatchCharacter(codepoint, fontStyle, fontWeight, fontStretch, culture, out typeface);
//Try to find a match with the system fonts
return SystemFonts.TryMatchCharacter(codepoint, fontStyle, fontWeight, fontStretch, fontFamily?.Name, culture, out typeface);
}

internal IReadOnlyList<Typeface> GetFamilyTypefaces(FontFamily fontFamily)
Expand Down
19 changes: 6 additions & 13 deletions src/Avalonia.Base/Media/Fonts/EmbeddedFontCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,15 @@ public override bool TryGetGlyphTypeface(string familyName, FontStyle style, Fon

private void AddGlyphTypeface(IGlyphTypeface glyphTypeface)
{
if (glyphTypeface is IGlyphTypeface2 glyphTypeface2)
//Add the TypographicFamilyName to the cache
if (!string.IsNullOrEmpty(glyphTypeface.TypographicFamilyName))
{
//Add the TypographicFamilyName to the cache
if (!string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
{
AddGlyphTypefaceByFamilyName(glyphTypeface2.TypographicFamilyName, glyphTypeface);
}

foreach (var kvp in glyphTypeface2.FamilyNames)
{
AddGlyphTypefaceByFamilyName(kvp.Value, glyphTypeface);
}
AddGlyphTypefaceByFamilyName(glyphTypeface.TypographicFamilyName, glyphTypeface);
}
else

foreach (var kvp in glyphTypeface.FamilyNames)
{
AddGlyphTypefaceByFamilyName(glyphTypeface.FamilyName, glyphTypeface);
AddGlyphTypefaceByFamilyName(kvp.Value, glyphTypeface);
}

return;
Expand Down
21 changes: 8 additions & 13 deletions src/Avalonia.Base/Media/Fonts/FontCollectionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public virtual bool TryMatchCharacter(int codepoint, FontStyle style, FontWeight
{
if (TryGetNearestMatch(glyphTypefaces, new FontCollectionKey { Style = style, Weight = weight, Stretch = stretch }, out var glyphTypeface))
{
if (glyphTypeface.TryGetGlyph((uint)codepoint, out _))
if (glyphTypeface.CharacterToGlyphMap.TryGetValue(codepoint, out _))
{
match = new Typeface(new FontFamily(null, Key.AbsoluteUri + "#" + glyphTypeface.FamilyName), style, weight, stretch);

Expand All @@ -55,7 +55,7 @@ public virtual bool TryMatchCharacter(int codepoint, FontStyle style, FontWeight

if (TryGetNearestMatch(glyphTypefaces, new FontCollectionKey { Style = style, Weight = weight, Stretch = stretch }, out var glyphTypeface))
{
if (glyphTypeface.TryGetGlyph((uint)codepoint, out _))
if (glyphTypeface.CharacterToGlyphMap.TryGetValue(codepoint, out _))
{
match = new Typeface(new FontFamily(null, Key.AbsoluteUri + "#" + glyphTypeface.FamilyName), style, weight, stretch);

Expand Down Expand Up @@ -94,36 +94,31 @@ public virtual bool TryCreateSyntheticGlyphTypeface(
return false;
}

if (glyphTypeface is not IGlyphTypeface2 glyphTypeface2)
{
return false;
}

var fontSimulations = FontSimulations.None;

if (style != FontStyle.Normal && glyphTypeface2.Style != style)
if (style != FontStyle.Normal && glyphTypeface.Style != style)
{
fontSimulations |= FontSimulations.Oblique;
}

if ((int)weight >= 600 && glyphTypeface2.Weight < weight)
if ((int)weight >= 600 && glyphTypeface.Weight < weight)
{
fontSimulations |= FontSimulations.Bold;
}

if (fontSimulations != FontSimulations.None && glyphTypeface2.TryGetStream(out var stream))
if (fontSimulations != FontSimulations.None && glyphTypeface.PlatformTypeface.TryGetStream(out var stream))
{
using (stream)
{
if (fontManager.TryCreateGlyphTypeface(stream, fontSimulations, out syntheticGlyphTypeface))
{
//Add the TypographicFamilyName to the cache
if (!string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
if (!string.IsNullOrEmpty(glyphTypeface.TypographicFamilyName))
{
AddGlyphTypefaceByFamilyName(glyphTypeface2.TypographicFamilyName, syntheticGlyphTypeface);
AddGlyphTypefaceByFamilyName(glyphTypeface.TypographicFamilyName, syntheticGlyphTypeface);
}

foreach (var kvp in glyphTypeface2.FamilyNames)
foreach (var kvp in glyphTypeface.FamilyNames)
{
AddGlyphTypefaceByFamilyName(kvp.Value, syntheticGlyphTypeface);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Base/Media/Fonts/OpenTypeTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Avalonia.Media.Fonts
{
internal readonly record struct OpenTypeTag
public readonly record struct OpenTypeTag
{
public static readonly OpenTypeTag None = new OpenTypeTag(0, 0, 0, 0);
public static readonly OpenTypeTag Max = new OpenTypeTag(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
Expand Down
41 changes: 35 additions & 6 deletions src/Avalonia.Base/Media/Fonts/SystemFontCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Avalonia.Platform;

Expand Down Expand Up @@ -135,9 +136,9 @@ private void LoadGlyphTypefaces(IFontManagerImpl fontManager, Uri source)
}

//Add TypographicFamilyName to the cache
if (glyphTypeface is IGlyphTypeface2 glyphTypeface2 && !string.IsNullOrEmpty(glyphTypeface2.TypographicFamilyName))
if (!string.IsNullOrEmpty(glyphTypeface.TypographicFamilyName))
{
AddGlyphTypefaceByFamilyName(glyphTypeface2.TypographicFamilyName, glyphTypeface);
AddGlyphTypefaceByFamilyName(glyphTypeface.TypographicFamilyName, glyphTypeface);
}

AddGlyphTypefaceByFamilyName(glyphTypeface.FamilyName, glyphTypeface);
Expand All @@ -161,13 +162,41 @@ void AddGlyphTypefaceByFamilyName(string familyName, IGlyphTypeface glyphTypefac
}
}

public bool TryGetFamilyTypefaces(string familyName, [NotNullWhen(true)] out IReadOnlyList<Typeface>? familyTypefaces)
public bool TryGetFamilyTypefaces(string familyName, [NotNullWhen(true)] out IReadOnlyList<Typeface>? familyTypefaces) =>
_fontManager.PlatformImpl.TryGetFamilyTypefaces(familyName, out familyTypefaces);

public override bool TryMatchCharacter(int codepoint, FontStyle style, FontWeight weight, FontStretch stretch, string? familyName, CultureInfo? culture, out Typeface typeface)
{
familyTypefaces = null;
if (base.TryMatchCharacter(codepoint, style, weight, stretch, familyName, culture, out typeface))
{
return true;
}

if (_fontManager.PlatformImpl is IFontManagerImpl2 fontManagerImpl2)
if (_fontManager.PlatformImpl.TryMatchCharacter(codepoint, style, weight, stretch, culture, out var match))
{
return fontManagerImpl2.TryGetFamilyTypefaces(familyName, out familyTypefaces);
var createdKey =
new FontCollectionKey(match.Style, match.Weight, match.Stretch);

var glyphTypeface = new GlyphTypeface(match, FontSimulations.None);

if (_glyphTypefaceCache.TryGetValue(glyphTypeface.FamilyName, out var glyphTypefaces))
{
if (!glyphTypefaces.TryAdd(createdKey, glyphTypeface))
{
return false;
}
}
else
{
if (!_glyphTypefaceCache.TryAdd(glyphTypeface.FamilyName, new ConcurrentDictionary<FontCollectionKey, IGlyphTypeface?>() { [createdKey] = glyphTypeface }))
{
return false;
}
}

typeface = new Typeface(glyphTypeface.FamilyName, match.Style, match.Weight, match.Stretch);

return true;
}

return false;
Expand Down
Loading
Loading