feat: add system font selection
This commit is contained in:
Executable
+119
@@ -0,0 +1,119 @@
|
||||
using System.Drawing;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
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> GetJpFonts() {
|
||||
var fonts = new List<string>();
|
||||
using var g = Graphics.FromImage(new Bitmap(1, 1));
|
||||
foreach (var (lpelfe, _, fontType) in Gdi32.EnumFontFamiliesEx(g.GetHdc(), CharacterSet.SHIFTJIS_CHARSET)) {
|
||||
var name = lpelfe.elfEnumLogfontEx.elfLogFont.lfFaceName;
|
||||
if (name.StartsWith("@")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fonts.Add(name);
|
||||
}
|
||||
|
||||
return fonts;
|
||||
}
|
||||
|
||||
internal static unsafe FontData? GetFont(string name, bool withItalic, CharacterSet charset = CharacterSet.ANSI_CHARSET) {
|
||||
var regularFont = Gdi32.CreateFontIndirect(new LOGFONT {
|
||||
lfFaceName = name,
|
||||
lfItalic = false,
|
||||
lfCharSet = charset,
|
||||
lfOutPrecision = LogFontOutputPrecision.OUT_TT_ONLY_PRECIS,
|
||||
});
|
||||
|
||||
using var g = Graphics.FromImage(new Bitmap(1, 1));
|
||||
var hdc = g.GetHdc();
|
||||
|
||||
byte[]? GetFontData(HGDIOBJ obj) {
|
||||
Gdi32.SelectObject(hdc, obj);
|
||||
var size = Gdi32.GetFontData(hdc, pvBuffer: IntPtr.Zero);
|
||||
var data = new byte[size];
|
||||
fixed (byte* p = data) {
|
||||
var res = Gdi32.GetFontData(hdc, pvBuffer: (IntPtr) p, cjBuffer: size);
|
||||
Gdi32.DeleteObject(obj);
|
||||
if (res == Gdi32.GDI_ERROR) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
var regular = GetFontData(regularFont);
|
||||
var italic = Array.Empty<byte>();
|
||||
if (withItalic) {
|
||||
var italicFont = Gdi32.CreateFontIndirect(new LOGFONT {
|
||||
lfFaceName = name,
|
||||
lfItalic = true,
|
||||
lfCharSet = charset,
|
||||
lfOutPrecision = LogFontOutputPrecision.OUT_TT_ONLY_PRECIS,
|
||||
});
|
||||
|
||||
italic = GetFontData(italicFont);
|
||||
}
|
||||
|
||||
if (regular == null || italic == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new FontData(regular, italic);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class FontData {
|
||||
internal byte[] Regular { get; }
|
||||
internal byte[] Italic { get; }
|
||||
|
||||
internal FontData(byte[] regular, byte[] italic) {
|
||||
this.Regular = regular;
|
||||
this.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) {
|
||||
this.Name = name;
|
||||
this.ResourcePath = resourcePath;
|
||||
this.ResourcePathItalic = resourcePathItalic;
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,8 @@ internal sealed class Settings : IUiComponent {
|
||||
var config = this.Ui.Plugin.Config;
|
||||
|
||||
var hideChatChanged = this.Mutable.HideChat != this.Ui.Plugin.Config.HideChat;
|
||||
var fontChanged = this.Mutable.GlobalFont != this.Ui.Plugin.Config.GlobalFont
|
||||
|| this.Mutable.JapaneseFont != this.Ui.Plugin.Config.JapaneseFont;
|
||||
var fontSizeChanged = Math.Abs(this.Mutable.FontSize - this.Ui.Plugin.Config.FontSize) > 0.001;
|
||||
|
||||
config.UpdateFrom(this.Mutable);
|
||||
@@ -131,7 +133,7 @@ internal sealed class Settings : IUiComponent {
|
||||
|
||||
this.Ui.Plugin.Store.FilterAllTabs(false);
|
||||
|
||||
if (fontSizeChanged) {
|
||||
if (fontChanged || fontSizeChanged) {
|
||||
this.Ui.Plugin.Interface.UiBuilder.RebuildFonts();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using ChatTwo.Resources;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using ChatTwo.Resources;
|
||||
using ChatTwo.Util;
|
||||
using ImGuiNET;
|
||||
|
||||
@@ -6,14 +8,32 @@ namespace ChatTwo.Ui.SettingsTabs;
|
||||
|
||||
internal sealed class Display : ISettingsTab {
|
||||
private Configuration Mutable { get; }
|
||||
private List<FontFamily> Fonts { get; } = new();
|
||||
private List<string> JpFonts { get; set; } = new();
|
||||
|
||||
public string Name => Language.Options_Display_Tab + "###tabs-display";
|
||||
|
||||
internal Display(Configuration mutable) {
|
||||
this.Mutable = mutable;
|
||||
this.UpdateFonts();
|
||||
}
|
||||
|
||||
private void UpdateFonts() {
|
||||
this.Fonts.Clear();
|
||||
|
||||
var fonts = new InstalledFontCollection();
|
||||
foreach (var font in fonts.Families) {
|
||||
this.Fonts.Add(font);
|
||||
}
|
||||
|
||||
this.JpFonts = Ui.Fonts.GetJpFonts();
|
||||
}
|
||||
|
||||
public void Draw() {
|
||||
if (ImGui.IsWindowAppearing()) {
|
||||
this.UpdateFonts();
|
||||
}
|
||||
|
||||
ImGuiUtil.OptionCheckbox(ref this.Mutable.HideChat, Language.Options_HideChat_Name, Language.Options_HideChat_Description);
|
||||
ImGuiUtil.OptionCheckbox(ref this.Mutable.HideDuringCutscenes, Language.Options_HideDuringCutscenes_Name, Language.Options_HideDuringCutscenes_Description);
|
||||
ImGuiUtil.OptionCheckbox(ref this.Mutable.NativeItemTooltips, Language.Options_NativeItemTooltips_Name, Language.Options_NativeItemTooltips_Description);
|
||||
@@ -28,6 +48,62 @@ internal sealed class Display : ISettingsTab {
|
||||
|
||||
ImGuiUtil.OptionCheckbox(ref this.Mutable.ShowNoviceNetwork, Language.Options_ShowNoviceNetwork_Name, Language.Options_ShowNoviceNetwork_Description);
|
||||
|
||||
if (ImGui.BeginCombo("Font", this.Mutable.GlobalFont)) {
|
||||
foreach (var font in Ui.Fonts.GlobalFonts) {
|
||||
if (ImGui.Selectable(font.Name, this.Mutable.GlobalFont == font.Name)) {
|
||||
this.Mutable.GlobalFont = font.Name;
|
||||
}
|
||||
|
||||
if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == font.Name) {
|
||||
ImGui.SetScrollHereY(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
foreach (var family in this.Fonts) {
|
||||
if (!family.IsStyleAvailable(FontStyle.Italic)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ImGui.Selectable(family.Name, this.Mutable.GlobalFont == family.Name)) {
|
||||
this.Mutable.GlobalFont = family.Name;
|
||||
}
|
||||
|
||||
if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == family.Name) {
|
||||
ImGui.SetScrollHereY(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui.BeginCombo("Japanese font", this.Mutable.JapaneseFont)) {
|
||||
foreach (var (name, _) in Ui.Fonts.JapaneseFonts) {
|
||||
if (ImGui.Selectable(name, this.Mutable.JapaneseFont == name)) {
|
||||
this.Mutable.JapaneseFont = name;
|
||||
}
|
||||
|
||||
if (ImGui.IsWindowAppearing() && this.Mutable.JapaneseFont == name) {
|
||||
ImGui.SetScrollHereY(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// ImGui.Separator();
|
||||
//
|
||||
// foreach (var family in this.JpFonts) {
|
||||
// if (ImGui.Selectable(family, this.Mutable.JapaneseFont == family)) {
|
||||
// this.Mutable.JapaneseFont = family;
|
||||
// }
|
||||
//
|
||||
// if (ImGui.IsWindowAppearing() && this.Mutable.JapaneseFont == family) {
|
||||
// ImGui.SetScrollHereY(0.5f);
|
||||
// }
|
||||
// }
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.DragFloat(Language.Options_FontSize_Name, ref this.Mutable.FontSize, .0125f, 12f, 36f, $"{this.Mutable.FontSize:N1}");
|
||||
if (ImGui.DragFloat(Language.Options_WindowOpacity_Name, ref this.Mutable.WindowAlpha, .0025f, 0f, 1f, $"{this.Mutable.WindowAlpha * 100f:N2}%%")) {
|
||||
switch (this.Mutable.WindowAlpha) {
|
||||
|
||||
Reference in New Issue
Block a user