Add FontAwesome fixed width (#1737)

* Add FA-FW

* remove braces (ask of kizer)

* reuse iconfont glyphs

* use FAFS for initial font

---------

Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
This commit is contained in:
rootdarkarchon 2024-04-14 23:19:27 +02:00 committed by GitHub
parent b8802f0609
commit e97d95dba8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 87 additions and 11 deletions

View file

@ -25,10 +25,15 @@ using Dalamud.Interface.Utility;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Utility; using Dalamud.Utility;
using Dalamud.Utility.Timing; using Dalamud.Utility.Timing;
using ImGuiNET; using ImGuiNET;
using ImGuiScene; using ImGuiScene;
using PInvoke; using PInvoke;
using Serilog; using Serilog;
using SharpDX; using SharpDX;
using SharpDX.Direct3D; using SharpDX.Direct3D;
using SharpDX.Direct3D11; using SharpDX.Direct3D11;
@ -131,6 +136,13 @@ internal class InterfaceManager : IInternalDisposableService
public static ImFontPtr IconFont => public static ImFontPtr IconFont =>
WhenFontsReady().IconFontHandle!.LockUntilPostFrame().OrElse(ImGui.GetIO().FontDefault); WhenFontsReady().IconFontHandle!.LockUntilPostFrame().OrElse(ImGui.GetIO().FontDefault);
/// <summary>
/// Gets an included FontAwesome icon font with fixed width.
/// <strong>Accessing this static property outside of the main thread is dangerous and not supported.</strong>
/// </summary>
public static ImFontPtr IconFontFixedWidth =>
WhenFontsReady().IconFontFixedWidthHandle!.LockUntilPostFrame().OrElse(ImGui.GetIO().FontDefault);
/// <summary> /// <summary>
/// Gets an included monospaced font.<br /> /// Gets an included monospaced font.<br />
/// <strong>Accessing this static property outside of the main thread is dangerous and not supported.</strong> /// <strong>Accessing this static property outside of the main thread is dangerous and not supported.</strong>
@ -148,6 +160,11 @@ internal class InterfaceManager : IInternalDisposableService
/// </summary> /// </summary>
public FontHandle? IconFontHandle { get; private set; } public FontHandle? IconFontHandle { get; private set; }
/// <summary>
/// Gets the icon font handle with fixed width.
/// </summary>
public FontHandle? IconFontFixedWidthHandle { get; private set; }
/// <summary> /// <summary>
/// Gets the mono font handle. /// Gets the mono font handle.
/// </summary> /// </summary>
@ -732,6 +749,13 @@ internal class InterfaceManager : IInternalDisposableService
GlyphMinAdvanceX = DefaultFontSizePx, GlyphMinAdvanceX = DefaultFontSizePx,
GlyphMaxAdvanceX = DefaultFontSizePx, GlyphMaxAdvanceX = DefaultFontSizePx,
}))); })));
this.IconFontFixedWidthHandle = (FontHandle)this.dalamudAtlas.NewDelegateFontHandle(
e => e.OnPreBuild(tk => tk.AddDalamudAssetFont(
DalamudAsset.FontAwesomeFreeSolid,
new()
{
GlyphRanges = new ushort[] { 0x20 },
})));
this.MonoFontHandle = (FontHandle)this.dalamudAtlas.NewDelegateFontHandle( this.MonoFontHandle = (FontHandle)this.dalamudAtlas.NewDelegateFontHandle(
e => e.OnPreBuild( e => e.OnPreBuild(
tk => tk.AddDalamudAssetFont( tk => tk.AddDalamudAssetFont(
@ -748,6 +772,13 @@ internal class InterfaceManager : IInternalDisposableService
tk.GetFont(this.DefaultFontHandle), tk.GetFont(this.DefaultFontHandle),
tk.GetFont(this.MonoFontHandle), tk.GetFont(this.MonoFontHandle),
missingOnly: true); missingOnly: true);
// Fill missing glyphs in IconFontFixedWidth with IconFont and fit ratio
tk.CopyGlyphsAcrossFonts(
tk.GetFont(this.IconFontHandle),
tk.GetFont(this.IconFontFixedWidthHandle),
missingOnly: true);
tk.FitRatio(tk.GetFont(this.IconFontFixedWidthHandle));
}); });
this.DefaultFontHandle.ImFontChanged += (_, font) => this.DefaultFontHandle.ImFontChanged += (_, font) =>
{ {

View file

@ -1,4 +1,4 @@
using Dalamud.Interface.Internal; using Dalamud.Interface.Internal;
using Dalamud.Utility; using Dalamud.Utility;
using ImGuiNET; using ImGuiNET;
@ -27,6 +27,13 @@ public interface IFontAtlasBuildToolkitPostBuild : IFontAtlasBuildToolkit
/// <returns>The texture index.</returns> /// <returns>The texture index.</returns>
int StoreTexture(IDalamudTextureWrap textureWrap, bool disposeOnError); int StoreTexture(IDalamudTextureWrap textureWrap, bool disposeOnError);
/// <summary>
/// Fits a font to a fixed 1:1 ratio adjusting glyph positions horizontally and vertically to fit within font size boundaries.
/// </summary>
/// <param name="font">The font to fit.</param>
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
void FitRatio(ImFontPtr font, bool rebuildLookupTable = true);
/// <summary> /// <summary>
/// Copies glyphs across fonts, in a safer way.<br /> /// Copies glyphs across fonts, in a safer way.<br />
/// If the font does not belong to the current atlas, this function is a no-op. /// If the font does not belong to the current atlas, this function is a no-op.

View file

@ -1,4 +1,4 @@
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@ -391,12 +391,10 @@ internal sealed partial class FontAtlasFactory
}); });
case DalamudAsset.LodestoneGameSymbol when !this.factory.HasGameSymbolsFontFile: case DalamudAsset.LodestoneGameSymbol when !this.factory.HasGameSymbolsFontFile:
{
return this.AddGameGlyphs( return this.AddGameGlyphs(
new(GameFontFamily.Axis, fontConfig.SizePx), new(GameFontFamily.Axis, fontConfig.SizePx),
fontConfig.GlyphRanges, fontConfig.GlyphRanges,
fontConfig.MergeFont); fontConfig.MergeFont);
}
default: default:
return this.factory.AddFont( return this.factory.AddFont(
@ -858,5 +856,30 @@ internal sealed partial class FontAtlasFactory
} }
} }
} }
/// <inheritdoc/>
public void FitRatio(ImFontPtr font, bool rebuildLookupTable = true)
{
var nsize = font.FontSize;
var glyphs = font.GlyphsWrapped();
foreach (ref var glyph in glyphs.DataSpan)
{
var ratio = 1f;
if (glyph.X1 - glyph.X0 > nsize)
ratio = Math.Max(ratio, (glyph.X1 - glyph.X0) / nsize);
if (glyph.Y1 - glyph.Y0 > nsize)
ratio = Math.Max(ratio, (glyph.Y1 - glyph.Y0) / nsize);
var w = MathF.Round((glyph.X1 - glyph.X0) / ratio, MidpointRounding.ToZero);
var h = MathF.Round((glyph.Y1 - glyph.Y0) / ratio, MidpointRounding.AwayFromZero);
glyph.X0 = MathF.Round((nsize - w) / 2f, MidpointRounding.ToZero);
glyph.Y0 = MathF.Round((nsize - h) / 2f, MidpointRounding.AwayFromZero);
glyph.X1 = glyph.X0 + w;
glyph.Y1 = glyph.Y0 + h;
glyph.AdvanceX = nsize;
}
if (rebuildLookupTable)
this.BuildLookupTable(font);
}
} }
} }

View file

@ -21,9 +21,13 @@ using Dalamud.Plugin;
using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Internal.Types;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Dalamud.Utility; using Dalamud.Utility;
using ImGuiNET; using ImGuiNET;
using ImGuiScene; using ImGuiScene;
using Serilog; using Serilog;
using SharpDX.Direct3D11; using SharpDX.Direct3D11;
namespace Dalamud.Interface; namespace Dalamud.Interface;
@ -53,6 +57,7 @@ public sealed class UiBuilder : IDisposable
private IFontHandle? defaultFontHandle; private IFontHandle? defaultFontHandle;
private IFontHandle? iconFontHandle; private IFontHandle? iconFontHandle;
private IFontHandle? monoFontHandle; private IFontHandle? monoFontHandle;
private IFontHandle? iconFontFixedWidthHandle;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UiBuilder"/> class and registers it. /// Initializes a new instance of the <see cref="UiBuilder"/> class and registers it.
@ -251,6 +256,16 @@ public sealed class UiBuilder : IDisposable
this.InterfaceManagerWithScene?.IconFontHandle this.InterfaceManagerWithScene?.IconFontHandle
?? throw new InvalidOperationException("Scene is not yet ready."))); ?? throw new InvalidOperationException("Scene is not yet ready.")));
/// <summary>
/// Gets the default Dalamud icon font based on FontAwesome 5 free solid with a fixed width and vertically centered glyphs.
/// </summary>
public IFontHandle IconFontFixedWidthHandle =>
this.iconFontFixedWidthHandle ??=
this.scopedFinalizer.Add(
new FontHandleWrapper(
this.InterfaceManagerWithScene?.IconFontFixedWidthHandle
?? throw new InvalidOperationException("Scene is not yet ready.")));
/// <summary> /// <summary>
/// Gets the default Dalamud monospaced font based on Inconsolata Regular. /// Gets the default Dalamud monospaced font based on Inconsolata Regular.
/// </summary> /// </summary>