aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBond-009 <bond.009@outlook.com>2026-03-29 14:28:41 -0400
committerBond_009 <bond.009@outlook.com>2026-03-29 14:28:41 -0400
commita3960b30c04d5313b0bfb3d57a7da35af5e8af3b (patch)
tree2003fd6185dbf275a6c7b7bbba3ec99ed1f25c7c
parentea206f43a25700904bc9c909d6616dfe55ab8671 (diff)
Backport pull request #16369 from jellyfin/release-10.11.z
Fix nullref ex in font handling Original-merge: 41c2d51d8cb9b4f9bdf81be6e73f7ae2d447a8d7 Merged-by: Bond-009 <bond.009@outlook.com> Backported-by: Bond_009 <bond.009@outlook.com>
-rw-r--r--src/Jellyfin.Drawing.Skia/SkiaEncoder.cs57
1 files changed, 37 insertions, 20 deletions
diff --git a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
index c6eab92ea..ade993d92 100644
--- a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
+++ b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
@@ -25,7 +25,7 @@ public class SkiaEncoder : IImageEncoder
private readonly ILogger<SkiaEncoder> _logger;
private readonly IApplicationPaths _appPaths;
private static readonly SKImageFilter _imageFilter;
- private static readonly SKTypeface[] _typefaces;
+ private static readonly SKTypeface?[] _typefaces = InitializeTypefaces();
/// <summary>
/// The default sampling options, equivalent to old high quality filter settings when upscaling.
@@ -37,9 +37,7 @@ public class SkiaEncoder : IImageEncoder
/// </summary>
public static readonly SKSamplingOptions DefaultSamplingOptions;
-#pragma warning disable CA1810
static SkiaEncoder()
-#pragma warning restore CA1810
{
var kernel = new[]
{
@@ -59,21 +57,6 @@ public class SkiaEncoder : IImageEncoder
SKShaderTileMode.Clamp,
true);
- // Initialize the list of typefaces
- // We have to statically build a list of typefaces because MatchCharacter only accepts a single character or code point
- // But in reality a human-readable character (grapheme cluster) could be multiple code points. For example, πŸš΅πŸ»β€β™€οΈ is a single emoji but 5 code points (U+1F6B5 + U+1F3FB + U+200D + U+2640 + U+FE0F)
- _typefaces =
- [
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 'ιΈ‘'), // CJK Simplified Chinese
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 'ι›ž'), // CJK Traditional Chinese
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 'γƒŽ'), // CJK Japanese
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, '각'), // CJK Korean
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 128169), // Emojis, 128169 is the πŸ’©emoji
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 'Χ–'), // Hebrew
- SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 'ي'), // Arabic
- SKTypeface.FromFamilyName("sans-serif", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright) // Default font
- ];
-
// use cubic for upscaling
UpscaleSamplingOptions = new SKSamplingOptions(SKCubicResampler.Mitchell);
// use bilinear for everything else
@@ -132,7 +115,7 @@ public class SkiaEncoder : IImageEncoder
/// <summary>
/// Gets the default typeface to use.
/// </summary>
- public static SKTypeface DefaultTypeFace => _typefaces.Last();
+ public static SKTypeface? DefaultTypeFace => _typefaces.Last();
/// <summary>
/// Check if the native lib is available.
@@ -153,6 +136,40 @@ public class SkiaEncoder : IImageEncoder
}
/// <summary>
+ /// Initialize the list of typefaces
+ /// We have to statically build a list of typefaces because MatchCharacter only accepts a single character or code point
+ /// But in reality a human-readable character (grapheme cluster) could be multiple code points. For example, πŸš΅πŸ»β€β™€οΈ is a single emoji but 5 code points (U+1F6B5 + U+1F3FB + U+200D + U+2640 + U+FE0F)
+ /// </summary>
+ /// <returns>The list of typefaces.</returns>
+ private static SKTypeface?[] InitializeTypefaces()
+ {
+ int[] chars = [
+ 'ιΈ‘', // CJK Simplified Chinese
+ 'ι›ž', // CJK Traditional Chinese
+ 'γƒŽ', // CJK Japanese
+ '각', // CJK Korean
+ 128169, // Emojis, 128169 is the Pile of Poo (πŸ’©) emoji
+ 'Χ–', // Hebrew
+ 'ي' // Arabic
+ ];
+ var fonts = new List<SKTypeface>(chars.Length + 1);
+ foreach (var ch in chars)
+ {
+ var font = SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, ch);
+ if (font is not null)
+ {
+ fonts.Add(font);
+ }
+ }
+
+ // Default font
+ fonts.Add(SKTypeface.FromFamilyName("sans-serif", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright)
+ ?? SKFontManager.Default.MatchCharacter(null, SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright, null, 'a'));
+
+ return fonts.ToArray();
+ }
+
+ /// <summary>
/// Convert a <see cref="ImageFormat"/> to a <see cref="SKEncodedImageFormat"/>.
/// </summary>
/// <param name="selectedFormat">The format to convert.</param>
@@ -809,7 +826,7 @@ public class SkiaEncoder : IImageEncoder
{
foreach (var typeface in _typefaces)
{
- if (typeface.ContainsGlyphs(c))
+ if (typeface is not null && typeface.ContainsGlyphs(c))
{
return typeface;
}