Skip to content

Commit

Permalink
Auto-enable fonts depending on the character input
Browse files Browse the repository at this point in the history
  • Loading branch information
Soreepeong committed Dec 10, 2023
1 parent 193e25d commit 8b07cdd
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 1 deletion.
68 changes: 68 additions & 0 deletions Dalamud/Interface/Internal/DalamudIme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Unicode;

using Dalamud.Game.Text;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.Utility;
using Dalamud.Logging.Internal;

Expand All @@ -26,6 +28,26 @@ internal sealed unsafe class DalamudIme : IDisposable, IServiceType
{
private static readonly ModuleLog Log = new("IME");

private static readonly UnicodeRange[] HanRange =
{
UnicodeRanges.CjkRadicalsSupplement,
UnicodeRanges.CjkSymbolsandPunctuation,
UnicodeRanges.CjkUnifiedIdeographsExtensionA,
UnicodeRanges.CjkUnifiedIdeographs,
UnicodeRanges.CjkCompatibilityIdeographs,
UnicodeRanges.CjkCompatibilityForms,
// No more; Extension B~ are outside BMP range
};

private static readonly UnicodeRange[] HangulRange =
{
UnicodeRanges.HangulJamo,
UnicodeRanges.HangulSyllables,
UnicodeRanges.HangulCompatibilityJamo,
UnicodeRanges.HangulJamoExtendedA,
UnicodeRanges.HangulJamoExtendedB,
};

private readonly ImGuiSetPlatformImeDataDelegate setPlatformImeDataDelegate;

[ServiceManager.ServiceConstructor]
Expand All @@ -38,6 +60,16 @@ internal sealed unsafe class DalamudIme : IDisposable, IServiceType

private delegate void ImGuiSetPlatformImeDataDelegate(ImGuiViewportPtr viewport, ImGuiPlatformImeDataPtr data);

/// <summary>
/// Gets a value indicating whether Han(Chinese) input has been detected.
/// </summary>
public bool EncounteredHan { get; private set; }

/// <summary>
/// Gets a value indicating whether Hangul(Korean) input has been detected.
/// </summary>
public bool EncounteredHangul { get; private set; }

/// <summary>
/// Gets a value indicating whether to display the cursor in input text. This also deals with blinking.
/// </summary>
Expand Down Expand Up @@ -116,6 +148,39 @@ public void Dispose()
GC.SuppressFinalize(this);
}

/// <summary>
/// Looks for the characters inside <paramref name="str"/> and enables fonts accordingly.
/// </summary>
/// <param name="str">The string.</param>
public void ReflectCharacterEncounters(string str)
{
foreach (var chr in str)
{
if (HanRange.Any(x => x.FirstCodePoint <= chr && chr < x.FirstCodePoint + x.Length))
{
if (Service<GameFontManager>.Get()
.GetFdtReader(GameFontFamilyAndSize.Axis12)
?.FindGlyph(chr) is null)
{
if (!this.EncounteredHan)
{
this.EncounteredHan = true;
Service<InterfaceManager>.Get().RebuildFonts();
}
}
}

if (HangulRange.Any(x => x.FirstCodePoint <= chr && chr < x.FirstCodePoint + x.Length))
{
if (!this.EncounteredHangul)
{
this.EncounteredHangul = true;
Service<InterfaceManager>.Get().RebuildFonts();
}
}
}
}

/// <summary>
/// Processes window messages.
/// </summary>
Expand Down Expand Up @@ -308,6 +373,8 @@ private void ReplaceCompositionString(HIMC hImc, uint comp)
? ImmGetCompositionString(hImc, GCS.GCS_RESULTSTR)
: ImmGetCompositionString(hImc, GCS.GCS_COMPSTR);

this.ReflectCharacterEncounters(newString);

if (s != e)
textState.DeleteChars(s, e - s);
textState.InsertChars(s, newString);
Expand Down Expand Up @@ -402,6 +469,7 @@ private void LoadCand(HIMC hImc)
(int)Math.Min(candlist.dwCount - candlist.dwPageStart, candlist.dwPageSize)))
{
this.ImmCand.Add(new((char*)(pStorage + candlist.dwOffset[i])));
this.ReflectCharacterEncounters(this.ImmCand[^1]);
}
}

Expand Down
56 changes: 55 additions & 1 deletion Dalamud/Interface/Internal/InterfaceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Unicode;
using System.Threading;

using Dalamud.Configuration.Internal;
Expand Down Expand Up @@ -786,10 +787,22 @@ private unsafe void SetupFonts()
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 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts", "malgun.ttf");
if (!File.Exists(fontPathKr))
fontPathKr = null;
Log.Verbose("[FONT] fontPathKr = {0}", fontPathKr);

var fontPathChs = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts", "msyh.ttc");
if (!File.Exists(fontPathChs))
fontPathChs = null;
Log.Verbose("[FONT] fontPathChs = {0}", fontPathChs);

var fontPathCht = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts", "msjh.ttc");
if (!File.Exists(fontPathCht))
fontPathCht = null;
Log.Verbose("[FONT] fontPathChs = {0}", fontPathCht);

// Default font
Log.Verbose("[FONT] SetupFonts - Default font");
var fontInfo = new TargetFontModification(
Expand Down Expand Up @@ -817,7 +830,8 @@ private unsafe void SetupFonts()
this.loadedFontInfo[DefaultFont] = fontInfo;
}

if (fontPathKr != null && Service<DalamudConfiguration>.Get().EffectiveLanguage == "ko")
if (fontPathKr != null
&& (Service<DalamudConfiguration>.Get().EffectiveLanguage == "ko" || this.dalamudIme.EncounteredHangul))
{
fontConfig.MergeMode = true;
fontConfig.GlyphRanges = ioFonts.GetGlyphRangesKorean();
Expand All @@ -826,6 +840,46 @@ private unsafe void SetupFonts()
fontConfig.MergeMode = false;
}

if (fontPathCht != null && Service<DalamudConfiguration>.Get().EffectiveLanguage == "tw")
{
fontConfig.MergeMode = true;
var rangeHandle = GCHandle.Alloc(new ushort[]
{
(ushort)UnicodeRanges.CjkUnifiedIdeographs.FirstCodePoint,
(ushort)(UnicodeRanges.CjkUnifiedIdeographs.FirstCodePoint +
(UnicodeRanges.CjkUnifiedIdeographs.Length - 1)),
(ushort)UnicodeRanges.CjkUnifiedIdeographsExtensionA.FirstCodePoint,
(ushort)(UnicodeRanges.CjkUnifiedIdeographsExtensionA.FirstCodePoint +
(UnicodeRanges.CjkUnifiedIdeographsExtensionA.Length - 1)),
0,
}, GCHandleType.Pinned);
garbageList.Add(rangeHandle);
fontConfig.GlyphRanges = rangeHandle.AddrOfPinnedObject();
fontConfig.PixelSnapH = true;
ioFonts.AddFontFromFileTTF(fontPathCht, fontConfig.SizePixels, fontConfig);
fontConfig.MergeMode = false;
}
else if (fontPathChs != null && (Service<DalamudConfiguration>.Get().EffectiveLanguage == "zh"
|| this.dalamudIme.EncounteredHan))
{
fontConfig.MergeMode = true;
var rangeHandle = GCHandle.Alloc(new ushort[]
{
(ushort)UnicodeRanges.CjkUnifiedIdeographs.FirstCodePoint,
(ushort)(UnicodeRanges.CjkUnifiedIdeographs.FirstCodePoint +
(UnicodeRanges.CjkUnifiedIdeographs.Length - 1)),
(ushort)UnicodeRanges.CjkUnifiedIdeographsExtensionA.FirstCodePoint,
(ushort)(UnicodeRanges.CjkUnifiedIdeographsExtensionA.FirstCodePoint +
(UnicodeRanges.CjkUnifiedIdeographsExtensionA.Length - 1)),
0,
}, GCHandleType.Pinned);
garbageList.Add(rangeHandle);
fontConfig.GlyphRanges = rangeHandle.AddrOfPinnedObject();
fontConfig.PixelSnapH = true;
ioFonts.AddFontFromFileTTF(fontPathChs, fontConfig.SizePixels, fontConfig);
fontConfig.MergeMode = false;
}

// FontAwesome icon font
Log.Verbose("[FONT] SetupFonts - FontAwesome icon font");
{
Expand Down

0 comments on commit 8b07cdd

Please sign in to comment.