diff --git a/ChatTwo/ChatTwo.csproj b/ChatTwo/ChatTwo.csproj
index 8f6244d..ebe4f5f 100755
--- a/ChatTwo/ChatTwo.csproj
+++ b/ChatTwo/ChatTwo.csproj
@@ -48,8 +48,7 @@
-
-
+
@@ -80,4 +79,4 @@
-
+
\ No newline at end of file
diff --git a/ChatTwo/PluginUi.cs b/ChatTwo/PluginUi.cs
index 2f0ffa1..c5ab658 100755
--- a/ChatTwo/PluginUi.cs
+++ b/ChatTwo/PluginUi.cs
@@ -32,9 +32,9 @@ internal sealed class PluginUi : IDisposable {
private List Components { get; }
private ImFontConfigPtr _fontCfg;
private ImFontConfigPtr _fontCfgMerge;
- private (GCHandle, int) _regularFont;
- private (GCHandle, int) _italicFont;
- private (GCHandle, int) _jpFont;
+ private (GCHandle, int, float) _regularFont;
+ private (GCHandle, int, float) _italicFont;
+ private (GCHandle, int, float) _jpFont;
private (GCHandle, int) _gameSymFont;
private readonly ImVector _ranges;
@@ -121,10 +121,18 @@ internal sealed class PluginUi : IDisposable {
if (this.Plugin.Config.GlobalFont.StartsWith(Fonts.IncludedIndicator)) {
var globalFont = Fonts.GlobalFonts.FirstOrDefault(font => font.Name == this.Plugin.Config.GlobalFont);
if (globalFont != null) {
- fontData = new FontData(this.GetResource(globalFont.ResourcePath), this.GetResource(globalFont.ResourcePathItalic));
+ var regular = new FaceData(this.GetResource(globalFont.ResourcePath), 1f);
+ var italic = new FaceData(this.GetResource(globalFont.ResourcePathItalic), 1f);
+ fontData = new FontData(regular, italic);
}
} else {
fontData = Fonts.GetFont(this.Plugin.Config.GlobalFont, true);
+ if (fontData != null) {
+ File.WriteAllBytes(@"D:\font.ttf", fontData.Regular.Data);
+ if (fontData.Italic != null) {
+ File.WriteAllBytes(@"D:\font_italic.ttf", fontData.Italic.Data);
+ }
+ }
}
if (fontData == null) {
@@ -132,7 +140,9 @@ internal sealed class PluginUi : IDisposable {
this.Plugin.SaveConfig();
var globalFont = Fonts.GlobalFonts[0];
- fontData = new FontData(this.GetResource(globalFont.ResourcePath), this.GetResource(globalFont.ResourcePathItalic));
+ var regular = new FaceData(this.GetResource(globalFont.ResourcePath), 1f);
+ var italic = new FaceData(this.GetResource(globalFont.ResourcePathItalic), 1f);
+ fontData = new FontData(regular, italic);
}
if (this._regularFont.Item1.IsAllocated) {
@@ -144,20 +154,25 @@ internal sealed class PluginUi : IDisposable {
}
this._regularFont = (
- GCHandle.Alloc(fontData.Regular, GCHandleType.Pinned),
- fontData.Regular.Length
+ GCHandle.Alloc(fontData.Regular.Data, GCHandleType.Pinned),
+ fontData.Regular.Data.Length,
+ fontData.Regular.Ratio
);
this._italicFont = (
- GCHandle.Alloc(fontData.Italic, GCHandleType.Pinned),
- fontData.Italic.Length
+ GCHandle.Alloc(fontData.Italic!.Data, GCHandleType.Pinned),
+ fontData.Italic.Data.Length,
+ fontData.Italic.Ratio
);
FontData? jpFontData = null;
if (this.Plugin.Config.JapaneseFont.StartsWith(Fonts.IncludedIndicator)) {
var jpFont = Fonts.JapaneseFonts.FirstOrDefault(item => item.Item1 == this.Plugin.Config.JapaneseFont);
if (jpFont != default) {
- jpFontData = new FontData(this.GetResource(jpFont.Item2), Array.Empty());
+ jpFontData = new FontData(
+ new FaceData(this.GetResource(jpFont.Item2), 1f),
+ null
+ );
}
}
// else {
@@ -170,7 +185,10 @@ internal sealed class PluginUi : IDisposable {
this.Plugin.SaveConfig();
var jpFont = Fonts.JapaneseFonts[0];
- jpFontData = new FontData(this.GetResource(jpFont.Item2), Array.Empty());
+ jpFontData = new FontData(
+ new FaceData(this.GetResource(jpFont.Item2), 1f),
+ null
+ );
}
if (this._jpFont.Item1.IsAllocated) {
@@ -178,8 +196,9 @@ internal sealed class PluginUi : IDisposable {
}
this._jpFont = (
- GCHandle.Alloc(jpFontData.Regular, GCHandleType.Pinned),
- jpFontData.Regular.Length
+ GCHandle.Alloc(jpFontData.Regular.Data, GCHandleType.Pinned),
+ jpFontData.Regular.Data.Length,
+ jpFontData.Regular.Ratio
);
}
diff --git a/ChatTwo/Ui/Fonts.cs b/ChatTwo/Ui/Fonts.cs
index a4b83bc..36ddcfd 100755
--- a/ChatTwo/Ui/Fonts.cs
+++ b/ChatTwo/Ui/Fonts.cs
@@ -1,5 +1,7 @@
-using System.Drawing;
-using Vanara.PInvoke;
+using System.Runtime.InteropServices;
+using Dalamud.Logging;
+using SharpDX.DirectWrite;
+using FontStyle = SharpDX.DirectWrite.FontStyle;
namespace ChatTwo.Ui;
@@ -34,73 +36,131 @@ internal static class Fonts {
// ($"{IncludedIndicator}Noto Serif JP", "ChatTwo.fonts.NotoSerifJP-Regular.otf"),
};
- internal static List GetJpFonts() {
+ internal static List GetFonts() {
var fonts = new List();
- 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("@")) {
+
+ 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);
+ PluginLog.Log(family.FamilyNames.GetString(0));
+ var anyItalic = false;
+ for (var j = 0; j < family.FontCount; j++) {
+ using var font = family.GetFont(j);
+ if (font.Style is not (FontStyle.Italic or FontStyle.Oblique)) {
+ continue;
+ }
+
+ anyItalic = true;
+ break;
+ }
+
+ if (!anyItalic) {
continue;
}
+ var name = family.FamilyNames.GetString(0);
fonts.Add(name);
}
+ fonts.Sort();
+ return fonts;
+ }
+
+ internal static List GetJpFonts() {
+ var fonts = new List();
+ // 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;
- }
+ 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;
}
- return data;
+ 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);
+
+ var metrics = font.Metrics;
+ var ratio = (metrics.Ascent + metrics.Descent + metrics.LineGap) / (float) metrics.DesignUnitsPerEm;
+
+ return new FaceData(data, ratio);
+ }
+
+ 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);
}
- var regular = GetFontData(regularFont);
- var italic = Array.Empty();
- if (withItalic) {
- var italicFont = Gdi32.CreateFontIndirect(new LOGFONT {
- lfFaceName = name,
- lfItalic = true,
- lfCharSet = charset,
- lfOutPrecision = LogFontOutputPrecision.OUT_TT_ONLY_PRECIS,
- });
+ return null;
+ }
+}
- italic = GetFontData(italicFont);
- }
+internal sealed class FaceData {
+ internal byte[] Data { get; }
+ internal float Ratio { get; }
- if (regular == null || italic == null) {
- return null;
- }
-
- return new FontData(regular, italic);
+ internal FaceData(byte[] data, float ratio) {
+ this.Data = data;
+ this.Ratio = ratio;
}
}
internal sealed class FontData {
- internal byte[] Regular { get; }
- internal byte[] Italic { get; }
+ internal FaceData Regular { get; }
+ internal FaceData? Italic { get; }
- internal FontData(byte[] regular, byte[] italic) {
+ internal FontData(FaceData regular, FaceData? italic) {
this.Regular = regular;
this.Italic = italic;
}
diff --git a/ChatTwo/Ui/SettingsTabs/Display.cs b/ChatTwo/Ui/SettingsTabs/Display.cs
index 5120597..bd9e49d 100755
--- a/ChatTwo/Ui/SettingsTabs/Display.cs
+++ b/ChatTwo/Ui/SettingsTabs/Display.cs
@@ -1,5 +1,3 @@
-using System.Drawing;
-using System.Drawing.Text;
using ChatTwo.Resources;
using ChatTwo.Util;
using ImGuiNET;
@@ -8,7 +6,7 @@ namespace ChatTwo.Ui.SettingsTabs;
internal sealed class Display : ISettingsTab {
private Configuration Mutable { get; }
- private List Fonts { get; } = new();
+ private List Fonts { get; set; } = new();
private List JpFonts { get; set; } = new();
public string Name => Language.Options_Display_Tab + "###tabs-display";
@@ -19,13 +17,7 @@ internal sealed class Display : ISettingsTab {
}
private void UpdateFonts() {
- this.Fonts.Clear();
-
- var fonts = new InstalledFontCollection();
- foreach (var font in fonts.Families) {
- this.Fonts.Add(font);
- }
-
+ this.Fonts = Ui.Fonts.GetFonts();
this.JpFonts = Ui.Fonts.GetJpFonts();
}
@@ -74,16 +66,12 @@ internal sealed class Display : ISettingsTab {
ImGui.Separator();
- foreach (var family in this.Fonts) {
- if (!family.IsStyleAvailable(FontStyle.Italic)) {
- continue;
+ foreach (var name in this.Fonts) {
+ if (ImGui.Selectable(name, this.Mutable.GlobalFont == name)) {
+ this.Mutable.GlobalFont = name;
}
- if (ImGui.Selectable(family.Name, this.Mutable.GlobalFont == family.Name)) {
- this.Mutable.GlobalFont = family.Name;
- }
-
- if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == family.Name) {
+ if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == name) {
ImGui.SetScrollHereY(0.5f);
}
}