Fix font size problems

This commit is contained in:
Soreepeong 2022-04-07 10:40:50 +09:00
parent b7a1303829
commit a97fc42d1e
2 changed files with 104 additions and 89 deletions

View file

@ -177,6 +177,9 @@ namespace Dalamud.Interface.GameFonts
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param> /// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
public static void UnscaleFont(ImFontPtr fontPtr, float fontScale, bool rebuildLookupTable = true) public static void UnscaleFont(ImFontPtr fontPtr, float fontScale, bool rebuildLookupTable = true)
{ {
if (fontScale == 1)
return;
unsafe unsafe
{ {
var font = fontPtr.NativePtr; var font = fontPtr.NativePtr;

View file

@ -55,7 +55,7 @@ namespace Dalamud.Interface.Internal
private readonly string rtssPath; private readonly string rtssPath;
private readonly HashSet<SpecialGlyphRequest> glyphRequests = new(); private readonly HashSet<SpecialGlyphRequest> glyphRequests = new();
private readonly List<GameFontHandle> axisFontHandles = new(); private readonly Dictionary<ImFontPtr, TargetFontModification> loadedFontInfo = new();
private readonly Hook<PresentDelegate> presentHook; private readonly Hook<PresentDelegate> presentHook;
private readonly Hook<ResizeBuffersDelegate> resizeBuffersHook; private readonly Hook<ResizeBuffersDelegate> resizeBuffersHook;
@ -594,15 +594,48 @@ namespace Dalamud.Interface.Internal
ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;
} }
private unsafe class TargetFontModification : IDisposable
{
internal TargetFontModification(string name, AxisMode axis, float sizePx, float scale)
{
this.Name = name;
this.Axis = axis;
this.TargetSizePx = sizePx;
this.Scale = scale;
this.SourceAxis = Service<GameFontManager>.Get().NewFontRef(new(GameFontFamily.Axis, sizePx * scale * 3 / 4));
}
internal enum AxisMode
{
Suppress,
GameGlyphsOnly,
Overwrite,
}
internal string Name { get; private init; }
internal AxisMode Axis { get; private init; }
internal float TargetSizePx { get; private init; }
internal float Scale { get; private init; }
internal GameFontHandle? SourceAxis { get; private init; }
internal bool SourceAxisAvailable => this.SourceAxis != null && this.SourceAxis.ImFont.NativePtr != null;
public void Dispose()
{
this.SourceAxis?.Dispose();
}
}
private unsafe void SetupFonts(int scaler = 0) private unsafe void SetupFonts(int scaler = 0)
{ {
var gameFontManager = Service<GameFontManager>.Get(); var gameFontManager = Service<GameFontManager>.Get();
var dalamud = Service<Dalamud>.Get(); var dalamud = Service<Dalamud>.Get();
var io = ImGui.GetIO(); var io = ImGui.GetIO();
var ioFonts = io.Fonts; var ioFonts = io.Fonts;
List<ImFontPtr> fontsToUnscale = new();
List<bool> fontsToOverwriteFromAxis = new();
List<float?> fontsToReassignSizes = new();
var maxTexDimension = 1 << (10 + Math.Max(0, Math.Min(4, this.FontResolutionLevel))); var maxTexDimension = 1 << (10 + Math.Max(0, Math.Min(4, this.FontResolutionLevel)));
var disableBigFonts = scaler != 0; var disableBigFonts = scaler != 0;
@ -615,13 +648,10 @@ namespace Dalamud.Interface.Internal
Log.Verbose("[FONT] SetupFonts - 1"); Log.Verbose("[FONT] SetupFonts - 1");
foreach (var v in this.axisFontHandles) foreach (var v in this.loadedFontInfo)
{ v.Value.Dispose();
if (v != null)
v.Dispose();
}
this.axisFontHandles.Clear(); this.loadedFontInfo.Clear();
Log.Verbose("[FONT] SetupFonts - 2"); Log.Verbose("[FONT] SetupFonts - 2");
@ -643,17 +673,19 @@ namespace Dalamud.Interface.Internal
// Default font // Default font
Log.Verbose("[FONT] SetupFonts - Default font"); Log.Verbose("[FONT] SetupFonts - Default font");
this.axisFontHandles.Add(gameFontManager.NewFontRef(new(GameFontFamily.Axis, DefaultFontSizePt * fontLoadScale))); var fontInfo = new TargetFontModification(
Log.Verbose("[FONT] SetupFonts - Default corresponding AXIS size: {0}pt ({1}px)", this.axisFontHandles.Last().Style.SizePt, this.axisFontHandles.Last().Style.SizePx); "Default",
this.UseAxis ? TargetFontModification.AxisMode.Overwrite : TargetFontModification.AxisMode.GameGlyphsOnly,
this.UseAxis ? DefaultFontSizePx : DefaultFontSizePx + 1,
fontLoadScale);
Log.Verbose("[FONT] SetupFonts - Default corresponding AXIS size: {0}pt ({1}px)", fontInfo.SourceAxis.Style.SizePt, fontInfo.SourceAxis.Style.SizePx);
if (this.UseAxis) if (this.UseAxis)
{ {
fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject();
fontConfig.SizePixels = DefaultFontSizePx * fontLoadScale; fontConfig.SizePixels = fontInfo.TargetSizePx;
fontConfig.PixelSnapH = false; fontConfig.PixelSnapH = false;
DefaultFont = ioFonts.AddFontDefault(fontConfig); DefaultFont = ioFonts.AddFontDefault(fontConfig);
fontsToUnscale.Add(DefaultFont); this.loadedFontInfo[DefaultFont] = fontInfo;
fontsToOverwriteFromAxis.Add(true);
fontsToReassignSizes.Add(disableBigFonts ? DefaultFontSizePx : null);
} }
else else
{ {
@ -662,10 +694,8 @@ namespace Dalamud.Interface.Internal
fontConfig.GlyphRanges = japaneseRangeHandle.AddrOfPinnedObject(); fontConfig.GlyphRanges = japaneseRangeHandle.AddrOfPinnedObject();
fontConfig.PixelSnapH = true; fontConfig.PixelSnapH = true;
DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontLoadScale, fontConfig); DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontInfo.TargetSizePx * fontLoadScale, fontConfig);
fontsToUnscale.Add(DefaultFont); this.loadedFontInfo[DefaultFont] = fontInfo;
fontsToOverwriteFromAxis.Add(false);
fontsToReassignSizes.Add(null);
} }
// FontAwesome icon font // FontAwesome icon font
@ -681,10 +711,7 @@ namespace Dalamud.Interface.Internal
fontConfig.GlyphRanges = iconRangeHandle.AddrOfPinnedObject(); fontConfig.GlyphRanges = iconRangeHandle.AddrOfPinnedObject();
fontConfig.PixelSnapH = true; fontConfig.PixelSnapH = true;
IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontLoadScale, fontConfig); IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontLoadScale, fontConfig);
fontsToUnscale.Add(IconFont); this.loadedFontInfo[IconFont] = new("Icon", TargetFontModification.AxisMode.GameGlyphsOnly, DefaultFontSizePx, fontLoadScale);
this.axisFontHandles.Add(null);
fontsToOverwriteFromAxis.Add(false);
fontsToReassignSizes.Add(null);
} }
// Monospace font // Monospace font
@ -697,10 +724,7 @@ namespace Dalamud.Interface.Internal
fontConfig.GlyphRanges = IntPtr.Zero; fontConfig.GlyphRanges = IntPtr.Zero;
fontConfig.PixelSnapH = true; fontConfig.PixelSnapH = true;
MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontLoadScale, fontConfig); MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontLoadScale, fontConfig);
fontsToUnscale.Add(MonoFont); this.loadedFontInfo[MonoFont] = new("Mono", TargetFontModification.AxisMode.GameGlyphsOnly, DefaultFontSizePx, fontLoadScale);
this.axisFontHandles.Add(null);
fontsToOverwriteFromAxis.Add(false);
fontsToReassignSizes.Add(null);
} }
// Default font but in requested size for requested glyphs // Default font but in requested size for requested glyphs
@ -748,31 +772,33 @@ namespace Dalamud.Interface.Internal
flattenedRanges.Add(0); flattenedRanges.Add(0);
ImFontPtr sizedFont; fontInfo = new(
this.axisFontHandles.Add(gameFontManager.NewFontRef(new(GameFontFamily.Axis, (disableBigFonts ? DefaultFontSizePt : fontSize * 3 / 4) * fontLoadScale))); $"Requested({fontSize}px)",
this.UseAxis ? TargetFontModification.AxisMode.Overwrite : TargetFontModification.AxisMode.GameGlyphsOnly,
fontSize,
fontLoadScale);
if (this.UseAxis) if (this.UseAxis)
{ {
fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject();
fontConfig.SizePixels = this.axisFontHandles.Last().Style.SizePx; fontConfig.SizePixels = fontInfo.SourceAxis.Style.SizePx;
fontConfig.PixelSnapH = false; fontConfig.PixelSnapH = false;
sizedFont = ioFonts.AddFontDefault(fontConfig);
fontsToUnscale.Add(sizedFont); var sizedFont = ioFonts.AddFontDefault(fontConfig);
fontsToOverwriteFromAxis.Add(true); this.loadedFontInfo[sizedFont] = fontInfo;
fontsToReassignSizes.Add(disableBigFonts ? fontSize : null); foreach (var request in requests)
request.FontInternal = sizedFont;
} }
else else
{ {
var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned);
garbageList.Add(rangeHandle); garbageList.Add(rangeHandle);
fontConfig.PixelSnapH = true; fontConfig.PixelSnapH = true;
sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, (disableBigFonts ? DefaultFontSizePx + 1 : fontSize) * fontLoadScale, fontConfig, rangeHandle.AddrOfPinnedObject());
fontsToUnscale.Add(sizedFont);
fontsToOverwriteFromAxis.Add(false);
fontsToReassignSizes.Add(disableBigFonts ? fontSize : null);
}
foreach (var request in requests) var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, (disableBigFonts ? DefaultFontSizePx + 1 : fontSize) * fontLoadScale, fontConfig, rangeHandle.AddrOfPinnedObject());
request.FontInternal = sizedFont; this.loadedFontInfo[sizedFont] = fontInfo;
foreach (var request in requests)
request.FontInternal = sizedFont;
}
} }
} }
@ -786,11 +812,13 @@ namespace Dalamud.Interface.Internal
for (int i = customFontFirstConfigIndex, i_ = ioFonts.ConfigData.Size; i < i_; i++) for (int i = customFontFirstConfigIndex, i_ = ioFonts.ConfigData.Size; i < i_; i++)
{ {
var configPtr = ioFonts.ConfigData[i].NativePtr; var config = ioFonts.ConfigData[i];
configPtr->OversampleH = 1; config.OversampleH = 1;
configPtr->OversampleV = 1; config.OversampleV = 1;
if (disableBigFonts)
configPtr->SizePixels = DefaultFontSizePx * fontLoadScale; var name = Encoding.UTF8.GetString((byte*)config.Name.Data, config.Name.Count).TrimEnd('\0');
this.loadedFontInfo[config.DstFont.NativePtr] = new($"PluginRequest({name})", TargetFontModification.AxisMode.Suppress, config.SizePixels, 1);
config.SizePixels = (disableBigFonts ? DefaultFontSizePx : config.SizePixels) * fontLoadScale;
} }
ioFonts.Build(); ioFonts.Build();
@ -819,60 +847,44 @@ namespace Dalamud.Interface.Internal
gameFontManager.AfterBuildFonts(); gameFontManager.AfterBuildFonts();
for (var i = 0; i < fontsToUnscale.Count; i++) foreach (var (font, mod) in this.loadedFontInfo)
{ {
var font = fontsToUnscale[i]; var nameBytes = Encoding.UTF8.GetBytes(mod.Name + "\0");
var fontPtr = font.NativePtr; Marshal.Copy(nameBytes, 0, (IntPtr)font.ConfigData.Name.Data, Math.Min(nameBytes.Length, font.ConfigData.Name.Count));
var correspondingAxis = this.axisFontHandles[i];
var overwrite = fontsToOverwriteFromAxis[i];
var overwriteSize = fontsToReassignSizes[i];
GameFontManager.UnscaleFont(font, fontLoadScale, false); Log.Verbose("[FONT] {0}: Unscale with scale value of {1}", mod.Name, mod.Scale);
GameFontManager.UnscaleFont(font, mod.Scale, false);
if (correspondingAxis == null) if (mod.Axis == TargetFontModification.AxisMode.Overwrite)
continue;
var scale = 1f;
if (overwrite)
{ {
var srcPtr = correspondingAxis.ImFont.NativePtr; Log.Verbose("[FONT] {0}: Overwrite from AXIS of size {1}px (was {2}px)", mod.Name, mod.SourceAxis.ImFont.FontSize, font.FontSize);
scale = fontPtr->ConfigData->SizePixels / srcPtr->ConfigData->SizePixels / fontLoadScale; font.FontSize = mod.SourceAxis.ImFont.FontSize;
fontPtr->FontSize = srcPtr->FontSize * scale; font.Ascent = mod.SourceAxis.ImFont.Ascent;
fontPtr->Ascent = srcPtr->Ascent * scale; font.Descent = mod.SourceAxis.ImFont.Descent;
fontPtr->Descent = srcPtr->Descent * scale; font.FallbackChar = mod.SourceAxis.ImFont.FallbackChar;
fontPtr->FallbackChar = srcPtr->FallbackChar; font.EllipsisChar = mod.SourceAxis.ImFont.EllipsisChar;
fontPtr->EllipsisChar = srcPtr->EllipsisChar; GameFontManager.CopyGlyphsAcrossFonts(mod.SourceAxis.ImFont, font, false, false);
GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, false, false); }
else if (mod.Axis == TargetFontModification.AxisMode.GameGlyphsOnly)
scale = 1f; {
Log.Verbose("[FONT] {0}: Overwrite game specific glyphs from AXIS of size {1}px", mod.Name, mod.SourceAxis.ImFont.FontSize, font.FontSize);
if (!this.UseAxis && font.NativePtr == DefaultFont.NativePtr)
mod.SourceAxis.ImFont.FontSize -= 1;
GameFontManager.CopyGlyphsAcrossFonts(mod.SourceAxis.ImFont, font, true, false, 0xE020, 0xE0DB);
if (!this.UseAxis && font.NativePtr == DefaultFont.NativePtr)
mod.SourceAxis.ImFont.FontSize += 1;
} }
if (overwriteSize != null) Log.Verbose("[FONT] {0}: Resize from {1}px to {2}px", mod.Name, font.FontSize, mod.TargetSizePx);
scale *= fontLoadScale * overwriteSize.Value / fontPtr->ConfigData->SizePixels; GameFontManager.UnscaleFont(font, font.FontSize / mod.TargetSizePx, false);
if (scale != 1f)
GameFontManager.UnscaleFont(font, 1 / scale, false);
Log.Verbose("[FONT] Font {0}: result size {1}", i, fontPtr->FontSize);
if (!this.UseAxis && fontPtr == DefaultFont.NativePtr)
{
fontPtr->FontSize -= 1;
GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, true, false, 0xE020, 0xE0DB);
fontPtr->FontSize += 1;
}
else
{
GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, true, false, 0xE020, 0xE0DB);
}
} }
// Fill missing glyphs in MonoFont from DefaultFont // Fill missing glyphs in MonoFont from DefaultFont
GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false);
foreach (var font in fontsToUnscale) for (int i = 0, i_ = ioFonts.Fonts.Size; i < i_; i++)
{ {
var font = ioFonts.Fonts[i];
font.FallbackChar = Fallback1Codepoint; font.FallbackChar = Fallback1Codepoint;
font.BuildLookupTable(); font.BuildLookupTable();
} }