Rewrite font handling, use dalamud font chooser

This commit is contained in:
Infi
2024-07-23 20:46:38 +02:00
parent f7252cdf78
commit 97654b1c53
11 changed files with 148 additions and 1330 deletions
+1 -1
View File
@@ -1683,7 +1683,7 @@ public sealed class ChatLogWindow : Window
var texSize = new Vector2(FontIcon!.Width, FontIcon.Height);
var sizeRatio = Plugin.Config.FontSize / entry.Height;
var sizeRatio = FontManager.GetFontSize() / entry.Height;
var size = new Vector2(entry.Width, entry.Height) * sizeRatio * ImGuiHelpers.GlobalScale;
var uv0 = new Vector2(entry.Left, entry.Top + 170) * 2 / texSize;
-196
View File
@@ -1,196 +0,0 @@
using System.Runtime.InteropServices;
using SharpDX;
using SharpDX.DirectWrite;
using FontStyle = SharpDX.DirectWrite.FontStyle;
namespace ChatTwo.Ui;
internal static class Fonts {
internal const string IncludedIndicator = "Chat 2: ";
internal static readonly Font[] GlobalFonts = {
new(
$"{IncludedIndicator}Noto Sans",
"ChatTwo.fonts.NotoSans-Regular.ttf",
"ChatTwo.fonts.NotoSans-Italic.ttf"
),
new(
$"{IncludedIndicator}Noto Serif",
"ChatTwo.fonts.NotoSerif-Regular.ttf",
"ChatTwo.fonts.NotoSerif-Italic.ttf"
),
new(
$"{IncludedIndicator}Open Sans",
"ChatTwo.fonts.OpenSans-Regular.ttf",
"ChatTwo.fonts.OpenSans-Italic.ttf"
),
new(
$"{IncludedIndicator}Roboto",
"ChatTwo.fonts.Roboto-Regular.ttf",
"ChatTwo.fonts.Roboto-Italic.ttf"
),
};
internal static readonly (string, string)[] JapaneseFonts = {
($"{IncludedIndicator}Noto Sans JP", "ChatTwo.fonts.NotoSansJP-Regular.otf"),
// ($"{IncludedIndicator}Noto Serif JP", "ChatTwo.fonts.NotoSerifJP-Regular.otf"),
};
internal static List<string> GetFonts() {
var fonts = new List<string>();
using var factory = new Factory();
using var collection = factory.GetSystemFontCollection(false);
for (var i = 0; i < collection.FontFamilyCount; i++) {
using var family = collection.GetFontFamily(i);
var anyItalic = false;
for (var j = 0; j < family.FontCount; j++) {
try {
var font = family.GetFont(j);
if (font.IsSymbolFont || font.Style is not (FontStyle.Italic or FontStyle.Oblique)) {
continue;
}
anyItalic = true;
break;
} catch (SharpDXException) {
// no-op
}
}
if (!anyItalic) {
continue;
}
var name = family.FamilyNames.GetString(0);
fonts.Add(name);
}
fonts.Sort();
return fonts;
}
internal static List<string> GetJpFonts() {
var fonts = new List<string>();
using var factory = new Factory();
using var collection = factory.GetSystemFontCollection(false);
for (var i = 0; i < collection.FontFamilyCount; i++) {
using var family = collection.GetFontFamily(i);
var probablyJp = false;
for (var j = 0; j < family.FontCount; j++) {
try {
using var font = family.GetFont(j);
if (!font.HasCharacter('気') || font.IsSymbolFont) {
continue;
}
probablyJp = true;
break;
} catch (SharpDXException) {
// no-op
}
}
if (!probablyJp) {
continue;
}
var name = family.FamilyNames.GetString(0);
fonts.Add(name);
}
fonts.Sort();
return fonts;
}
internal static FontData? GetFont(string name, bool withItalic) {
using var factory = new Factory();
using var collection = factory.GetSystemFontCollection(false);
for (var i = 0; i < collection.FontFamilyCount; i++) {
using var family = collection.GetFontFamily(i);
if (family.FamilyNames.GetString(0) != name) {
continue;
}
using var normal = family.GetFirstMatchingFont(FontWeight.Normal, FontStretch.Normal, FontStyle.Normal);
if (normal == null) {
return null;
}
FaceData? GetFontData(SharpDX.DirectWrite.Font font) {
using var face = new FontFace(font);
var files = face.GetFiles();
if (files.Length == 0) {
return null;
}
var key = files[0].GetReferenceKey();
using var stream = files[0].Loader.CreateStreamFromKey(key);
stream.ReadFileFragment(out var start, 0, stream.GetFileSize(), out var release);
var data = new byte[stream.GetFileSize()];
Marshal.Copy(start, data, 0, data.Length);
stream.ReleaseFileFragment(release);
return new FaceData(data);
}
var normalData = GetFontData(normal);
if (normalData == null) {
return null;
}
FaceData? italicData = null;
if (withItalic) {
using var italic = family.GetFirstMatchingFont(FontWeight.Normal, FontStretch.Normal, FontStyle.Italic)
?? family.GetFirstMatchingFont(FontWeight.Normal, FontStretch.Normal, FontStyle.Oblique);
if (italic == null) {
return null;
}
italicData = GetFontData(italic);
}
if (italicData == null && withItalic) {
return null;
}
return new FontData(normalData, italicData);
}
return null;
}
}
internal sealed class FaceData {
internal byte[] Data { get; }
internal FaceData(byte[] data) {
Data = data;
}
}
internal sealed class FontData {
internal FaceData Regular { get; }
internal FaceData? Italic { get; }
internal FontData(FaceData regular, FaceData? italic) {
Regular = regular;
Italic = italic;
}
}
internal sealed class Font {
internal string Name { get; }
internal string ResourcePath { get; }
internal string ResourcePathItalic { get; }
internal Font(string name, string resourcePath, string resourcePathItalic) {
Name = name;
ResourcePath = resourcePath;
ResourcePathItalic = resourcePathItalic;
}
}
+4 -5
View File
@@ -150,12 +150,11 @@ public sealed class SettingsWindow : Window
// calculate all conditions before updating config
var hideChanged = !Mutable.HideChat && Mutable.HideChat != Plugin.Config.HideChat;
var languageChanged = Mutable.LanguageOverride != Plugin.Config.LanguageOverride;
var fontChanged = Mutable.GlobalFont != Plugin.Config.GlobalFont
|| Mutable.JapaneseFont != Plugin.Config.JapaneseFont
var fontChanged = Mutable.GlobalFontV2 != Plugin.Config.GlobalFontV2
|| Mutable.JapaneseFontV3 != Plugin.Config.JapaneseFontV3
|| Mutable.ExtraGlyphRanges != Plugin.Config.ExtraGlyphRanges;
var fontSizeChanged = Math.Abs(Mutable.FontSize - Plugin.Config.FontSize) > 0.001
|| Math.Abs(Mutable.JapaneseFontSize - Plugin.Config.JapaneseFontSize) > 0.001
|| Math.Abs(Mutable.SymbolsFontSize - Plugin.Config.SymbolsFontSize) > 0.001;
var fontSizeChanged = Math.Abs(Mutable.SymbolsFontSizeV2 - Plugin.Config.SymbolsFontSizeV2) > 0.001
|| Math.Abs(Mutable.FontSizeV2 - Plugin.Config.FontSizeV2) > 0.001;
Plugin.Config.UpdateFrom(Mutable, true);
+2
View File
@@ -107,9 +107,11 @@ internal sealed class ChatLog : ISettingsTab
var currentStyle = Mutable.ChosenStyle ?? Language.Options_OverrideStyle_NotSelected;
using var combo = ImRaii.Combo(Language.Options_OverrideStyleDropdown_Name, currentStyle);
if (combo)
{
foreach (var style in styles)
if (ImGui.Selectable(style.Name, Mutable.ChosenStyle == style.Name))
Mutable.ChosenStyle = style.Name;
}
ImGui.Spacing();
}
+22 -68
View File
@@ -9,89 +9,47 @@ public class Fonts : ISettingsTab
private Configuration Mutable { get; }
public string Name => Language.Options_Fonts_Tab + "###tabs-fonts";
private List<string> GlobalFonts { get; set; } = [];
private List<string> JpFonts { get; set; } = [];
internal Fonts(Configuration mutable)
{
Mutable = mutable;
UpdateFonts();
}
private void UpdateFonts()
public void Draw(bool _)
{
GlobalFonts = Ui.Fonts.GetFonts();
JpFonts = Ui.Fonts.GetJpFonts();
}
public void Draw(bool changed)
{
if (changed)
UpdateFonts();
using var wrap = ImGuiUtil.TextWrapPos();
ImGui.Checkbox(Language.Options_FontsEnabled, ref Mutable.FontsEnabled);
ImGui.Spacing();
if (Mutable.FontsEnabled)
if (!Mutable.FontsEnabled)
{
using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Font_Name, Mutable.GlobalFont))
ImGuiUtil.FontSizeCombo(Language.Options_FontSize_Name, ref Mutable.FontSizeV2);
ImGuiUtil.HelpText($"[Old Size] {FontManager.SizeInPt(Mutable.FontSize)}pt"); // TODO Remove after 24.08
}
else
{
var globalChooser = ImGuiUtil.FontChooser(Language.Options_Font_Name, Mutable.GlobalFontV2);
globalChooser?.ResultTask.ContinueWith(r =>
{
if (combo)
{
foreach (var font in Ui.Fonts.GlobalFonts)
{
if (ImGui.Selectable(font.Name, Mutable.GlobalFont == font.Name))
Mutable.GlobalFont = font.Name;
if (ImGui.IsWindowAppearing() && Mutable.GlobalFont == font.Name)
ImGui.SetScrollHereY(0.5f);
}
ImGui.Separator();
foreach (var name in GlobalFonts)
{
if (ImGui.Selectable(name, Mutable.GlobalFont == name))
Mutable.GlobalFont = name;
if (ImGui.IsWindowAppearing() && Mutable.GlobalFont == name)
ImGui.SetScrollHereY(0.5f);
}
}
}
if (r.IsCompletedSuccessfully)
Mutable.GlobalFontV2 = r.Result;
});
ImGuiUtil.HelpText($"[Old Font] {Mutable.GlobalFont} ({FontManager.SizeInPt(Mutable.FontSize)}pt)"); // TODO Remove after 24.08
ImGuiUtil.HelpText(string.Format(Language.Options_Font_Description, Plugin.PluginName));
ImGuiUtil.WarningText(Language.Options_Font_Warning);
ImGui.Spacing();
using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_JapaneseFont_Name, Mutable.JapaneseFont))
// LocaleNames being null means it is likely a game font which all support JP symbols
var japaneseChooser = ImGuiUtil.FontChooser(Language.Options_JapaneseFont_Name, Mutable.JapaneseFontV3, id => !id.LocaleNames?.ContainsKey("ja-jp") ?? false, "いろはにほへと ちりぬるを");
japaneseChooser?.ResultTask.ContinueWith(r =>
{
if (combo)
{
foreach (var (name, _) in Ui.Fonts.JapaneseFonts)
{
if (ImGui.Selectable(name, Mutable.JapaneseFont == name))
Mutable.JapaneseFont = name;
if (ImGui.IsWindowAppearing() && Mutable.JapaneseFont == name)
ImGui.SetScrollHereY(0.5f);
}
ImGui.Separator();
foreach (var family in JpFonts)
{
if (ImGui.Selectable(family, Mutable.JapaneseFont == family))
Mutable.JapaneseFont = family;
if (ImGui.IsWindowAppearing() && Mutable.JapaneseFont == family)
ImGui.SetScrollHereY(0.5f);
}
}
}
if (r.IsCompletedSuccessfully)
Mutable.JapaneseFontV3 = r.Result;
});
ImGuiUtil.HelpText($"[Old Font] {Mutable.JapaneseFont} ({FontManager.SizeInPt(Mutable.JapaneseFontSize)}pt)"); // TODO Remove after 24.08
ImGuiUtil.HelpText(string.Format(Language.Options_JapaneseFont_Description, Plugin.PluginName));
ImGui.Spacing();
@@ -109,12 +67,8 @@ public class Fonts : ISettingsTab
ImGui.Spacing();
}
const float speed = .0125f;
const float min = 8f;
const float max = 36f;
ImGuiUtil.DragFloatVertical(Language.Options_FontSize_Name, ref Mutable.FontSize, speed, min, max, $"{Mutable.FontSize:N1}");
ImGuiUtil.DragFloatVertical(Language.Options_JapaneseFontSize_Name, ref Mutable.JapaneseFontSize, speed, min, max, $"{Mutable.JapaneseFontSize:N1}");
ImGuiUtil.DragFloatVertical(Language.Options_SymbolsFontSize_Name, ref Mutable.SymbolsFontSize, speed, min, max, $"{Mutable.SymbolsFontSize:N1}");
ImGuiUtil.FontSizeCombo(Language.Options_SymbolsFontSize_Name, ref Mutable.SymbolsFontSizeV2);
ImGuiUtil.HelpText($"[Old Size] {FontManager.SizeInPt(Mutable.SymbolsFontSize)}pt"); // TODO Remove after 24.08
ImGuiUtil.HelpText(Language.Options_SymbolsFontSize_Description);
ImGui.Spacing();