feat: Refactor CJK font resources into a TTC collection and add support for multi-language switching.

This commit is contained in:
Loskh 2025-12-12 16:58:48 +08:00
parent a39763f161
commit e6a9dcd740
7 changed files with 70 additions and 39 deletions

View file

@ -1,4 +1,4 @@
using Dalamud.Storage.Assets;
using Dalamud.Storage.Assets;
using TerraFX.Interop.DirectX;
@ -128,17 +128,17 @@ public enum DalamudAsset
/// <see cref="DalamudAssetPurpose.Font"/>: Noto Sans CJK JP Medium.
/// </summary>
[DalamudAsset(DalamudAssetPurpose.Font)]
[DalamudAssetPath("UIRes", "NotoSansCJKjp-Regular.otf")]
[DalamudAssetPath("UIRes", "NotoSansCJKjp-Medium.otf")]
NotoSansJpMedium = 2000,
//[DalamudAssetPath("UIRes", "NotoSansCJKjp-Regular.otf")]
[DalamudAssetPath("UIRes", "NotoSansCJK-Medium.ttc")]
NotoSansCJKMedium = 2000,
/// <summary>
/// <see cref="DalamudAssetPurpose.Font"/>: Noto Sans CJK KR Regular.
/// </summary>
[DalamudAsset(DalamudAssetPurpose.Font)]
[DalamudAssetPath("UIRes", "NotoSansCJKkr-Regular.otf")]
[DalamudAssetPath("UIRes", "NotoSansKR-Regular.otf")]
NotoSansKrRegular = 2001,
//[DalamudAssetPath("UIRes", "NotoSansCJKkr-Regular.otf")]
[DalamudAssetPath("UIRes", "NotoSansCJK-Regular.ttc")]
NotoSansCJKRegular = 2001,
/// <summary>
/// <see cref="DalamudAssetPurpose.Font"/>: Inconsolata Regular.

View file

@ -38,7 +38,8 @@ public interface IFontFamilyId : IObjectWithLocalizableName
public static List<IFontFamilyId> ListDalamudFonts() =>
new()
{
new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansJpMedium),
new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCJKMedium),
new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCJKRegular),
new DalamudAssetFontAndFamilyId(DalamudAsset.InconsolataRegular),
new DalamudAssetFontAndFamilyId(DalamudAsset.FontAwesomeFreeSolid),
};

View file

@ -24,6 +24,11 @@ public interface IFontSpec
/// </summary>
float LineHeightPx { get; }
/// <summary>
/// Gets the font no.
/// </summary>
int FontNo { get; }
/// <summary>
/// Creates a font handle corresponding to this font specification.
/// </summary>

View file

@ -65,6 +65,12 @@ public record SingleFontSpec : IFontSpec
[JsonProperty]
public ushort[]? GlyphRanges { get; init; }
/// <summary>
/// Gets the font no.
/// </summary>
[JsonProperty]
public int FontNo { get; init; }
/// <inheritdoc/>
public string ToLocalizedString(string localeCode)
{
@ -99,6 +105,7 @@ public record SingleFontSpec : IFontSpec
tk,
new()
{
FontNo = this.FontNo,
SizePx = this.SizePx,
GlyphRanges = this.GlyphRanges,
MergeFont = mergeFont,

View file

@ -128,7 +128,7 @@ public sealed class SingleFontChooserDialog : IDisposable
this.popupImGuiName = $"{this.title}##{nameof(SingleFontChooserDialog)}[{this.counter}]";
this.atlas = newAsyncAtlas;
this.selectedFont = new() { FontId = DalamudDefaultFontAndFamilyId.Instance };
Encoding.UTF8.GetBytes("Font preview.\n0123456789!", this.fontPreviewText);
Encoding.UTF8.GetBytes("Font preview.\n0123456789!\n遍角次亮采之门门上插刀、直字拐弯、天上平板、船顶漏雨。\n다람쥐 헌 쳇바퀴에 타고파", this.fontPreviewText);
}
/// <summary>Called when the selected font spec has changed.</summary>
@ -891,7 +891,21 @@ public sealed class SingleFontChooserDialog : IDisposable
this.selectedFontWeight = font.Weight;
this.selectedFontStretch = font.Stretch;
this.selectedFontStyle = font.Style;
this.selectedFont = this.selectedFont with { FontId = font };
int fontNo = 0;
if (family is DalamudAssetFontAndFamilyId { Asset: DalamudAsset.NotoSansCJKRegular or DalamudAsset.NotoSansCJKMedium })
{
var dalamudConfiguration = Service<DalamudConfiguration>.Get();
fontNo = dalamudConfiguration.EffectiveLanguage switch
{
"jp" => 0,
"tw" => 1,
"zh" => 2,
"ko" => 3,
_ => 0,
};
}
this.selectedFont = this.selectedFont with { FontId = font, FontNo = fontNo };
}
return changed;

View file

@ -371,10 +371,7 @@ internal sealed partial class FontAtlasFactory
return this.factory.AddFont(
this,
asset,
fontConfig with
{
FontNo = 0,
});
fontConfig);
}
}
@ -562,32 +559,39 @@ internal sealed partial class FontAtlasFactory
return;
var dalamudConfiguration = Service<DalamudConfiguration>.Get();
if (dalamudConfiguration.EffectiveLanguage == "ko"
|| Service<DalamudIme>.GetNullable()?.EncounteredHangul is true)
var ime = Service<DalamudIme>.GetNullable();
string langTag = null;
// fontNo: 0 = japanese, 1 = traditional chinese, 2 = simplified chinese, 3 = korean
int fontNo = 0;
if (dalamudConfiguration.EffectiveLanguage == "tw")
{
this.AddDalamudAssetFont(
DalamudAsset.NotoSansKrRegular,
fontConfig with
{
MergeFont = targetFont,
GlyphRanges = default(FluentGlyphRangeBuilder).WithLanguage("ko-kr").BuildExact(),
});
langTag = "zh-hant";
fontNo = 1;
}
else if (dalamudConfiguration.EffectiveLanguage == "zh" || ime?.EncounteredHan is true)
{
langTag = "zh-hans";
fontNo = 2;
}
else if (dalamudConfiguration.EffectiveLanguage == "ko" || ime?.EncounteredHangul is true)
{
langTag = "ko-kr";
fontNo = 3;
}
if (Service<DalamudConfiguration>.Get().EffectiveLanguage == "tw")
Log.Debug($"Loading extra glyphs for language tag '{langTag}' (font no {fontNo})");
if (langTag != null)
{
this.AttachWindowsDefaultFont(CultureInfo.GetCultureInfo("zh-hant"), fontConfig with
{
GlyphRanges = default(FluentGlyphRangeBuilder).WithLanguage("zh-hant").BuildExact(),
});
}
else if (Service<DalamudConfiguration>.Get().EffectiveLanguage == "zh"
|| Service<DalamudIme>.GetNullable()?.EncounteredHan is true)
{
this.AttachWindowsDefaultFont(CultureInfo.GetCultureInfo("zh-hans"), fontConfig with
{
GlyphRanges = default(FluentGlyphRangeBuilder).WithLanguage("zh-hans").BuildExact(),
});
this.AddDalamudAssetFont(
DalamudAsset.NotoSansCJKRegular,
fontConfig with
{
FontNo = fontNo,
MergeFont = targetFont,
GlyphRanges = default(FluentGlyphRangeBuilder).WithLanguage(langTag).BuildExact(),
});
}
}
@ -629,7 +633,7 @@ internal sealed partial class FontAtlasFactory
if (this.data.ConfigData.Length == 0)
{
this.AddDalamudAssetFont(
DalamudAsset.NotoSansJpMedium,
DalamudAsset.NotoSansCJKRegular,
new() { GlyphRanges = new ushort[] { ' ', ' ', '\0' }, SizePx = 1 });
}

View file

@ -412,7 +412,7 @@ internal class GamePrebakedFontHandle : FontHandle
private ImFontPtr CreateTemplateFont(IFontAtlasBuildToolkitPreBuild toolkitPreBuild, float sizePx)
{
var font = toolkitPreBuild.AddDalamudAssetFont(
DalamudAsset.NotoSansJpMedium,
DalamudAsset.NotoSansCJKMedium,
new()
{
GlyphRanges = new ushort[] { ' ', ' ', '\0' },