feat: add system font selection

This commit is contained in:
Anna
2022-02-04 23:00:16 -05:00
parent 38cdb98f2d
commit 45c7d85e33
13 changed files with 280 additions and 19 deletions
+119
View File
@@ -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;
}
}
+3 -1
View File
@@ -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();
}
+77 -1
View File
@@ -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) {