feat: use newer way of getting fonts
This commit is contained in:
parent
04735444f4
commit
e957b9ec76
|
@ -48,8 +48,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.5"/>
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0"/>
|
||||
<PackageReference Include="Vanara.PInvoke.Gdi32" Version="3.3.15"/>
|
||||
<PackageReference Include="SharpDX.Direct2D1" Version="4.2.0"/>
|
||||
<PackageReference Include="XivCommon" Version="5.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -80,4 +79,4 @@
|
|||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
|
@ -32,9 +32,9 @@ internal sealed class PluginUi : IDisposable {
|
|||
private List<IUiComponent> 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<byte>());
|
||||
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<byte>());
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<string> GetJpFonts() {
|
||||
internal static List<string> GetFonts() {
|
||||
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("@")) {
|
||||
|
||||
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<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;
|
||||
}
|
||||
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<byte>();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<FontFamily> Fonts { get; } = new();
|
||||
private List<string> Fonts { get; set; } = new();
|
||||
private List<string> 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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue