diff options
| author | Bond-009 <bond.009@outlook.com> | 2026-03-29 14:28:41 -0400 |
|---|---|---|
| committer | Bond_009 <bond.009@outlook.com> | 2026-03-29 14:28:41 -0400 |
| commit | a3960b30c04d5313b0bfb3d57a7da35af5e8af3b (patch) | |
| tree | 2003fd6185dbf275a6c7b7bbba3ec99ed1f25c7c | |
| parent | ea206f43a25700904bc9c909d6616dfe55ab8671 (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.cs | 57 |
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; } |
