Skip to content

Commit febe8ac

Browse files
committed
Fix potential NRE on some bare bones windows installs while trying to match fonts using skia sharp
1 parent 35a83cd commit febe8ac

2 files changed

Lines changed: 39 additions & 15 deletions

File tree

src/IronyModManager.Platform/Fonts/FontManager.cs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
// Created : 03-13-2021
55
//
66
// Last Modified By : Mario
7-
// Last Modified On : 10-27-2021
7+
// Last Modified On : 01-24-2026
88
// ***********************************************************************
99
// <copyright file="FontManager.cs" company="Mario">
1010
// Mario
1111
// </copyright>
1212
// <summary></summary>
1313
// ***********************************************************************
14+
1415
using System;
1516
using System.Collections.Generic;
1617
using System.Globalization;
@@ -51,7 +52,7 @@ internal class FontManager : IFontManagerImpl
5152
/// <summary>
5253
/// All fonts
5354
/// </summary>
54-
private List<string> allFonts = null;
55+
private List<string> allFonts;
5556

5657
/// <summary>
5758
/// The typefaces
@@ -90,18 +91,21 @@ public IGlyphTypefaceImpl CreateGlyphTypeface(Typeface typeface)
9091
{
9192
typeface = new Typeface(fontFamilyManager.ResolveFontFamily(typeface.FontFamily.Name).GetFontFamily(), typeface.Style, typeface.Weight);
9293
}
94+
9395
var fontCollection = SKTypefaceCollectionCache.GetOrAddTypefaceCollection(typeface.FontFamily);
9496
if (fontCollection == null)
9597
{
9698
// Fallback to Irony default
9799
typeface = new Typeface(fontFamilyManager.GetDefaultFontFamily().GetFontFamily(), typeface.Style, typeface.Weight);
98100
fontCollection = SKTypefaceCollectionCache.GetOrAddTypefaceCollection(typeface.FontFamily);
99101
}
102+
100103
var skTypeface = fontCollection.Get(typeface);
101104
if (skTypeface == null)
102105
{
103106
return fontManager.CreateGlyphTypeface(typeface);
104107
}
108+
105109
var isFakeBold = (int)typeface.Weight >= 600 && !skTypeface.IsBold;
106110
var isFakeItalic = typeface.Style == FontStyle.Italic && !skTypeface.IsItalic;
107111
return new GlyphTypefaceImpl(skTypeface, isFakeBold, isFakeItalic);
@@ -115,10 +119,12 @@ public IGlyphTypefaceImpl CreateGlyphTypeface(Typeface typeface)
115119
{
116120
return fontManager.CreateGlyphTypeface(typeface);
117121
}
122+
118123
var isFakeBold = (int)typeface.Weight >= 600 && !skTypeface.IsBold;
119124
var isFakeItalic = typeface.Style == FontStyle.Italic && !skTypeface.IsItalic;
120125
return new GlyphTypefaceImpl(skTypeface, isFakeBold, isFakeItalic);
121126
}
127+
122128
return fontManager.CreateGlyphTypeface(typeface);
123129
}
124130

@@ -149,8 +155,10 @@ public IEnumerable<string> GetInstalledFontFamilyNames(bool checkForUpdates = fa
149155
{
150156
fonts.AddRange(fontManager.GetInstalledFontFamilyNames(checkForUpdates));
151157
}
158+
152159
allFonts = fonts.Distinct().ToList();
153160
}
161+
154162
return allFonts;
155163
}
156164

@@ -168,28 +176,46 @@ public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fon
168176
{
169177
if (typefaces == null)
170178
{
171-
typefaces = new List<Typeface>();
179+
typefaces = [];
172180
foreach (var item in fontFamilyManager.GetAllFontNames())
173181
{
174182
typefaces.Add(new Typeface(fontFamilyManager.ResolveFontFamily(item).GetFontFamily()));
175183
}
176184
}
185+
177186
foreach (var item in typefaces)
178187
{
179188
if (item.GlyphTypeface.GetGlyph((uint)codepoint) == 0)
180189
{
181190
continue;
182191
}
192+
183193
typeface = new Typeface(item.FontFamily.Name, fontStyle, fontWeight);
184194
return true;
185195
}
186196

187197
if (GetPlatformConfiguration().GetOptions().Fonts.UseInbuiltFontsOnly)
188198
{
189-
var fallback = SKFontManager.Default.MatchCharacter(fontFamily?.Name, (SKFontStyleWeight)fontWeight, SKFontStyleWidth.Normal, (SKFontStyleSlant)fontStyle, new string[] { culture.ThreeLetterISOLanguageName, culture.TwoLetterISOLanguageName }, codepoint);
199+
SKTypeface fallback = null;
200+
if (SKFontManager.Default != null)
201+
{
202+
// Some OS / Skia builds can throw or return null from SKFontManager.Default.MatchCharacter.
203+
// Guard and fallback to Irony's bundled default font to avoid UI crashes.
204+
try
205+
{
206+
fallback = SKFontManager.Default.MatchCharacter(fontFamily?.Name, (SKFontStyleWeight)fontWeight, SKFontStyleWidth.Normal, (SKFontStyleSlant)fontStyle, [
207+
culture.ThreeLetterISOLanguageName, culture.TwoLetterISOLanguageName
208+
], codepoint);
209+
}
210+
catch
211+
{
212+
}
213+
}
214+
190215
typeface = new Typeface(fallback?.FamilyName ?? fontFamilyManager.GetDefaultFontFamily().GetFontFamily(), fontStyle, fontWeight);
191216
return true;
192217
}
218+
193219
return fontManager.TryMatchCharacter(codepoint, fontStyle, fontWeight, fontFamily, culture, out typeface);
194220
}
195221

@@ -199,10 +225,8 @@ public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fon
199225
/// <returns>IFontFamilyManager.</returns>
200226
private IFontFamilyManager GetFontFamilyManager()
201227
{
202-
if (fontFamilyManager == null)
203-
{
204-
fontFamilyManager = DIResolver.Get<IFontFamilyManager>();
205-
}
228+
fontFamilyManager ??= DIResolver.Get<IFontFamilyManager>();
229+
206230
return fontFamilyManager;
207231
}
208232

@@ -212,10 +236,8 @@ private IFontFamilyManager GetFontFamilyManager()
212236
/// <returns>IPlatformConfiguration.</returns>
213237
private IPlatformConfiguration GetPlatformConfiguration()
214238
{
215-
if (platformConfiguration == null)
216-
{
217-
platformConfiguration = DIResolver.Get<IPlatformConfiguration>();
218-
}
239+
platformConfiguration ??= DIResolver.Get<IPlatformConfiguration>();
240+
219241
return platformConfiguration;
220242
}
221243

src/IronyModManager.Platform/Fonts/SKTypefaceCollectionCache.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@
44
// Created : 03-13-2021
55
//
66
// Last Modified By : Mario
7-
// Last Modified On : 07-10-2022
7+
// Last Modified On : 01-24-2026
88
// ***********************************************************************
99
// <copyright file="SKTypefaceCollectionCache.cs" company="Avalonia">
1010
// Avalonia
1111
// </copyright>
1212
// <summary></summary>
1313
// ***********************************************************************
14+
1415
using System;
1516
using System.Collections.Concurrent;
1617
using System.Collections.Generic;
18+
using System.Diagnostics.CodeAnalysis;
1719
using System.Linq;
1820
using Avalonia;
1921
using Avalonia.Media;
@@ -27,6 +29,7 @@ namespace IronyModManager.Platform.Fonts
2729
/// <summary>
2830
/// Class SKTypefaceCollectionCache.
2931
/// </summary>
32+
[SuppressMessage("ReSharper", "InconsistentNaming")]
3033
internal static class SKTypefaceCollectionCache
3134
{
3235
#region Fields
@@ -59,7 +62,7 @@ static SKTypefaceCollectionCache()
5962
/// <returns>SKTypefaceCollection.</returns>
6063
public static SKTypefaceCollection GetOrAddTypefaceCollection(FontFamily fontFamily)
6164
{
62-
return cachedCollections.GetOrAdd(fontFamily, x => CreateCustomFontCollection(fontFamily));
65+
return cachedCollections.GetOrAdd(fontFamily, _ => CreateCustomFontCollection(fontFamily));
6366
}
6467

6568
/// <summary>
@@ -68,7 +71,6 @@ public static SKTypefaceCollection GetOrAddTypefaceCollection(FontFamily fontFam
6871
/// <param name="fontFamily">The font family.</param>
6972
/// <returns>SKTypefaceCollection.</returns>
7073
/// <exception cref="System.InvalidOperationException">Asset could not be loaded.</exception>
71-
7274
private static SKTypefaceCollection CreateCustomFontCollection(FontFamily fontFamily)
7375
{
7476
var fontAssets = FontFamilyLoader.LoadFontAssets(fontFamily.Key);

0 commit comments

Comments
 (0)