From 2a36122c2c861128b1ed26e028657c820de23d9a Mon Sep 17 00:00:00 2001 From: kizer Date: Sat, 23 Apr 2022 23:42:44 +0900 Subject: [PATCH] Prevent NPE, load Korean font if it exists (#802) Co-authored-by: goaaats --- .../Internal/DalamudConfiguration.cs | 34 +++++++++++++++- .../Interface/GameFonts/GameFontManager.cs | 23 ++++++++--- .../Interface/Internal/InterfaceManager.cs | 40 ++++++++++++++++--- .../Internal/Windows/SettingsWindow.cs | 21 +--------- 4 files changed, 88 insertions(+), 30 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index a77b94959..dbfb5488c 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; - +using System.Linq; using Dalamud.Game.Text; using Dalamud.Interface.GameFonts; using Dalamud.Interface.Style; @@ -311,6 +312,37 @@ namespace Dalamud.Configuration.Internal /// public bool IsMbCollect { get; set; } = true; + /// + /// Gets the ISO 639-1 two-letter code for the language of the effective Dalamud display language. + /// + public string EffectiveLanguage + { + get + { + var languages = Localization.ApplicableLangCodes.Prepend("en").ToArray(); + try + { + if (string.IsNullOrEmpty(this.LanguageOverride)) + { + var currentUiLang = CultureInfo.CurrentUICulture; + + if (Localization.ApplicableLangCodes.Any(x => currentUiLang.TwoLetterISOLanguageName == x)) + return currentUiLang.TwoLetterISOLanguageName; + else + return languages[0]; + } + else + { + return this.LanguageOverride; + } + } + catch (Exception) + { + return languages[0]; + } + } + } + /// /// Gets or sets a value indicating whether or not to show info on dev bar. /// diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index 2d52796a4..5a885bc8d 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -190,8 +190,8 @@ namespace Dalamud.Interface.GameFonts font->FontSize /= fontScale; font->Ascent /= fontScale; font->Descent /= fontScale; - for (int i = 0, i_ = font->ConfigDataCount; i < i_; i++) - font->ConfigData[i].SizePixels /= fontScale; + if (font->ConfigData != null) + font->ConfigData->SizePixels /= fontScale; var glyphs = (ImFontGlyphReal*)font->Glyphs.Data; for (int i = 0, i_ = font->Glyphs.Size; i < i_; i++) { @@ -356,7 +356,9 @@ namespace Dalamud.Interface.GameFonts var fdt = this.fdts[(int)(forceMinSize ? style.FamilyWithMinimumSize : style.FamilyAndSize)]; var scale = style.SizePt / fdt.FontHeader.Size; var fontPtr = font.NativePtr; - fontPtr->ConfigData->SizePixels = fontPtr->FontSize = fdt.FontHeader.Size * 4 / 3; + fontPtr->FontSize = fdt.FontHeader.Size * 4 / 3; + if (fontPtr->ConfigData != null) + fontPtr->ConfigData->SizePixels = fontPtr->FontSize; fontPtr->Ascent = fdt.FontHeader.Ascent; fontPtr->Descent = fdt.FontHeader.Descent; fontPtr->EllipsisChar = '…'; @@ -370,8 +372,19 @@ namespace Dalamud.Interface.GameFonts } } - var nameBytes = Encoding.UTF8.GetBytes(style.ToString() + "\0"); - Marshal.Copy(nameBytes, 0, (IntPtr)font.ConfigData.Name.Data, Math.Min(nameBytes.Length, font.ConfigData.Name.Count)); + // I have no idea what's causing NPE, so just to be safe + try + { + if (font.NativePtr != null && font.NativePtr->ConfigData != null) + { + var nameBytes = Encoding.UTF8.GetBytes(style.ToString() + "\0"); + Marshal.Copy(nameBytes, 0, (IntPtr)font.ConfigData.Name.Data, Math.Min(nameBytes.Length, font.ConfigData.Name.Count)); + } + } + catch (NullReferenceException) + { + // do nothing + } foreach (var (c, (rectId, glyph)) in this.glyphRectIds[style]) { diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 617ea14d8..d0f76e0fb 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -658,9 +658,19 @@ namespace Dalamud.Interface.Internal fontConfig.OversampleH = 1; fontConfig.OversampleV = 1; - var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); + var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Regular.otf"); + if (!File.Exists(fontPathJp)) + fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); if (!File.Exists(fontPathJp)) ShowFontError(fontPathJp); + Log.Verbose("[FONT] fontPathJp = {0}", fontPathJp); + + var fontPathKr = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKkr-Regular.otf"); + if (!File.Exists(fontPathKr)) + fontPathKr = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansKR-Regular.otf"); + if (!File.Exists(fontPathKr)) + fontPathKr = null; + Log.Verbose("[FONT] fontPathKr = {0}", fontPathKr); // Default font Log.Verbose("[FONT] SetupFonts - Default font"); @@ -671,10 +681,10 @@ namespace Dalamud.Interface.Internal io.FontGlobalScale, disableBigFonts); Log.Verbose("[FONT] SetupFonts - Default corresponding AXIS size: {0}pt ({1}px)", fontInfo.SourceAxis.Style.BaseSizePt, fontInfo.SourceAxis.Style.BaseSizePx); + fontConfig.SizePixels = disableBigFonts ? Math.Min(MinimumFallbackFontSizePx, fontInfo.TargetSizePx) : fontInfo.TargetSizePx * io.FontGlobalScale; if (this.UseAxis) { fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); - fontConfig.SizePixels = fontInfo.TargetSizePx; fontConfig.PixelSnapH = false; DefaultFont = ioFonts.AddFontDefault(fontConfig); this.loadedFontInfo[DefaultFont] = fontInfo; @@ -686,10 +696,19 @@ namespace Dalamud.Interface.Internal fontConfig.GlyphRanges = japaneseRangeHandle.AddrOfPinnedObject(); fontConfig.PixelSnapH = true; - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, disableBigFonts ? Math.Min(MinimumFallbackFontSizePx, fontInfo.TargetSizePx) : fontInfo.TargetSizePx * io.FontGlobalScale, fontConfig); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontConfig.SizePixels, fontConfig); this.loadedFontInfo[DefaultFont] = fontInfo; } + if (fontPathKr != null && Service.Get().EffectiveLanguage == "ko") + { + fontConfig.MergeMode = true; + fontConfig.GlyphRanges = ioFonts.GetGlyphRangesKorean(); + fontConfig.PixelSnapH = true; + ioFonts.AddFontFromFileTTF(fontPathKr, fontConfig.SizePixels, fontConfig); + fontConfig.MergeMode = false; + } + // FontAwesome icon font Log.Verbose("[FONT] SetupFonts - FontAwesome icon font"); { @@ -887,8 +906,19 @@ namespace Dalamud.Interface.Internal foreach (var (font, mod) in this.loadedFontInfo) { - var nameBytes = Encoding.UTF8.GetBytes(mod.Name + "\0"); - Marshal.Copy(nameBytes, 0, (IntPtr)font.ConfigData.Name.Data, Math.Min(nameBytes.Length, font.ConfigData.Name.Count)); + // I have no idea what's causing NPE, so just to be safe + try + { + if (font.NativePtr != null && font.NativePtr->ConfigData != null) + { + var nameBytes = Encoding.UTF8.GetBytes($"{mod.Name}\0"); + Marshal.Copy(nameBytes, 0, (IntPtr)font.ConfigData.Name.Data, Math.Min(nameBytes.Length, font.ConfigData.Name.Count)); + } + } + catch (NullReferenceException) + { + // do nothing + } Log.Verbose("[FONT] {0}: Unscale with scale value of {1}", mod.Name, mod.Scale); GameFontManager.UnscaleFont(font, mod.Scale, false); diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index e79b8cc82..dec061a9b 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -134,26 +134,9 @@ namespace Dalamud.Interface.Internal.Windows }; this.languages = Localization.ApplicableLangCodes.Prepend("en").ToArray(); - try - { - if (string.IsNullOrEmpty(configuration.LanguageOverride)) - { - var currentUiLang = CultureInfo.CurrentUICulture; - - if (Localization.ApplicableLangCodes.Any(x => currentUiLang.TwoLetterISOLanguageName == x)) - this.langIndex = Array.IndexOf(this.languages, currentUiLang.TwoLetterISOLanguageName); - else - this.langIndex = 0; - } - else - { - this.langIndex = Array.IndexOf(this.languages, configuration.LanguageOverride); - } - } - catch (Exception) - { + this.langIndex = Array.IndexOf(this.languages, configuration.EffectiveLanguage); + if (this.langIndex == -1) this.langIndex = 0; - } try {