Files
HellionChat/ChatTwo/FontManager.cs
T
2026-03-22 15:03:37 +01:00

160 lines
5.8 KiB
C#

using Dalamud.Interface;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.Utility;
using Dalamud.Bindings.ImGui;
namespace ChatTwo;
public class FontManager
{
internal IFontHandle Axis { get; private set; }
internal IFontHandle AxisItalic { get; private set; }
internal IFontHandle RegularFont { get; private set; }
internal IFontHandle? ItalicFont { get; private set; }
internal IFontHandle FontAwesome { get; private set; }
internal readonly byte[] GameSymFont;
private ushort[] Ranges;
private ushort[] JpRange;
public static readonly HashSet<float> AxisFontSizeList =
[
9.6f, 10f, 12f, 14f, 16f,
18f, 18.4f, 20f, 23f, 34f,
36f, 40f, 45f, 46f, 68f, 90f,
];
public FontManager()
{
var filePath = Path.Combine(Plugin.Interface.ConfigDirectory.FullName, "FFXIV_Lodestone_SSF.ttf");
if (File.Exists(filePath))
{
GameSymFont = File.ReadAllBytes(filePath);
}
else
{
GameSymFont = new HttpClient().GetAsync("https://img.finalfantasyxiv.com/lds/pc/global/fonts/FFXIV_Lodestone_SSF.ttf")
.Result
.Content
.ReadAsByteArrayAsync()
.Result;
Dalamud.Utility.FilesystemUtil.WriteAllBytesSafe(filePath, GameSymFont);
}
}
private unsafe void SetUpRanges()
{
ushort[] BuildRange(IReadOnlyList<ushort>? chars, params nint[] ranges)
{
var builder = new ImFontGlyphRangesBuilderPtr(ImGuiNative.ImFontGlyphRangesBuilder());
// text
foreach (var range in ranges)
builder.AddRanges((ushort*)range);
// chars
if (chars != null)
{
for (var i = 0; i < chars.Count; i += 2)
{
if (chars[i] == 0)
break;
for (var j = (uint) chars[i]; j <= chars[i + 1]; j++)
builder.AddChar((ushort) j);
}
}
// various symbols
// French
// Romanian
builder.AddText("←→↑↓《》■※☀★★☆♥♡ヅツッシ☀☁☂℃℉°♀♂♠♣♦♣♧®©™€$£♯♭♪✓√◎◆◇♦■□〇●△▽▼▲‹›≤≥<«“”─\~");
builder.AddText("Œœ");
builder.AddText("ĂăÂâÎîȘșȚț");
// "Enclosed Alphanumerics" (partial) https://www.compart.com/en/unicode/block/U+2460
for (var i = 0x2460; i <= 0x24B5; i++)
builder.AddChar((char) i);
builder.AddChar('⓪');
return builder.BuildRangesToArray();
}
var ranges = new List<nint> { (nint)ImGui.GetIO().Fonts.GetGlyphRangesDefault() };
foreach (var extraRange in Enum.GetValues<ExtraGlyphRanges>())
if (Plugin.Config.ExtraGlyphRanges.HasFlag(extraRange))
ranges.Add(extraRange.Range());
Ranges = BuildRange(null, ranges.ToArray());
JpRange = BuildRange(GlyphRangesJapanese.GlyphRanges);
}
public void BuildFonts()
{
SetUpRanges();
Axis = Plugin.Interface.UiBuilder.FontAtlas.NewGameFontHandle(new GameFontStyle(GameFontFamily.Axis, SizeInPx(Plugin.Config.FontSizeV2)));
AxisItalic = Plugin.Interface.UiBuilder.FontAtlas.NewGameFontHandle(new GameFontStyle(GameFontFamily.Axis, SizeInPx(Plugin.Config.FontSizeV2))
{
SkewStrength = SizeInPx(Plugin.Config.FontSizeV2) / 6
});
FontAwesome = Plugin.Interface.UiBuilder.FontAtlas.NewDelegateFontHandle(e =>
{
e.OnPreBuild(tk => tk.AddFontAwesomeIconFont(new SafeFontConfig { SizePx = GetFontSize() }));
e.OnPostBuild(tk => tk.FitRatio(tk.Font));
});
RegularFont = Plugin.Interface.UiBuilder.FontAtlas.NewDelegateFontHandle(
e => e.OnPreBuild(
tk =>
{
var config = new SafeFontConfig {SizePt = Plugin.Config.GlobalFontV2.SizePt, GlyphRanges = Ranges};
config.MergeFont = Plugin.Config.GlobalFontV2.FontId.AddToBuildToolkit(tk, config);
config.SizePt = Plugin.Config.JapaneseFontV2.SizePt;
config.GlyphRanges = JpRange;
Plugin.Config.JapaneseFontV2.FontId.AddToBuildToolkit(tk, config);
config.SizePt = Plugin.Config.SymbolsFontSizeV2;
tk.AddGameSymbol(config);
tk.Font = config.MergeFont;
}
));
if (Plugin.Config.ItalicEnabled)
{
ItalicFont = Plugin.Interface.UiBuilder.FontAtlas.NewDelegateFontHandle(
e => e.OnPreBuild(
tk =>
{
var config = new SafeFontConfig {SizePt = Plugin.Config.ItalicFontV2.SizePt, GlyphRanges = Ranges};
config.MergeFont = Plugin.Config.ItalicFontV2.FontId.AddToBuildToolkit(tk, config);
config.SizePt = Plugin.Config.JapaneseFontV2.SizePt;
config.GlyphRanges = JpRange;
Plugin.Config.JapaneseFontV2.FontId.AddToBuildToolkit(tk, config);
config.SizePt = Plugin.Config.SymbolsFontSizeV2;
tk.AddGameSymbol(config);
tk.Font = config.MergeFont;
}
));
}
else
{
ItalicFont = null;
}
}
public static float SizeInPt(float px) => (float) (px * 3.0 / 4.0);
public static float SizeInPx(float pt) => (float) (pt * 4.0 / 3.0);
public static float GetFontSize() => Plugin.Config.FontsEnabled ? Plugin.Config.GlobalFontV2.SizePx : SizeInPx(Plugin.Config.FontSizeV2);
}