diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index cb5426f48..2d52796a4 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Runtime.InteropServices; using System.Text; using Dalamud.Configuration.Internal; @@ -229,7 +230,10 @@ namespace Dalamud.Interface.GameFonts } if (needRebuild) + { + Log.Information("[GameFontManager] Calling RebuildFonts because {0} has been requested.", style.ToString()); this.interfaceManager.RebuildFonts(); + } return new(this, style); } @@ -287,7 +291,8 @@ namespace Dalamud.Interface.GameFonts /// /// Build fonts before plugins do something more. To be called from InterfaceManager. /// - public void BuildFonts() + /// Whether to load fonts in minimum sizes. + public void BuildFonts(bool forceMinSize) { unsafe { @@ -305,7 +310,7 @@ namespace Dalamud.Interface.GameFonts { var rectIds = this.glyphRectIds[style] = new(); - var fdt = this.fdts[(int)style.FamilyAndSize]; + var fdt = this.fdts[(int)(forceMinSize ? style.FamilyWithMinimumSize : style.FamilyAndSize)]; if (fdt == null) continue; @@ -318,7 +323,7 @@ namespace Dalamud.Interface.GameFonts if (c < 32 || c >= 0xFFFF) continue; - var widthAdjustment = style.CalculateWidthAdjustment(fdt, glyph); + var widthAdjustment = style.CalculateBaseWidthAdjustment(fdt, glyph); rectIds[c] = Tuple.Create( io.Fonts.AddCustomRectFontGlyph( font, @@ -338,7 +343,8 @@ namespace Dalamud.Interface.GameFonts /// /// Post-build fonts before plugins do something more. To be called from InterfaceManager. /// - public unsafe void AfterBuildFonts() + /// Whether to load fonts in minimum sizes. + public unsafe void AfterBuildFonts(bool forceMinSize) { var ioFonts = ImGui.GetIO().Fonts; ioFonts.GetTexDataAsRGBA32(out byte* pixels8, out var width, out var height); @@ -347,7 +353,8 @@ namespace Dalamud.Interface.GameFonts foreach (var (style, font) in this.fonts) { - var fdt = this.fdts[(int)style.FamilyAndSize]; + var fdt = this.fdts[(int)(forceMinSize ? style.FamilyWithMinimumSize : style.FamilyAndSize)]; + var scale = style.SizePt / fdt.FontHeader.Size; var fontPtr = font.NativePtr; fontPtr->ConfigData->SizePixels = fontPtr->FontSize = fdt.FontHeader.Size * 4 / 3; fontPtr->Ascent = fdt.FontHeader.Ascent; @@ -363,19 +370,15 @@ namespace Dalamud.Interface.GameFonts } } - fixed (char* c = FontNames[(int)style.FamilyAndSize]) - { - for (var j = 0; j < 40; j++) - fontPtr->ConfigData->Name[j] = 0; - Encoding.UTF8.GetBytes(c, FontNames[(int)style.FamilyAndSize].Length, fontPtr->ConfigData->Name, 40); - } + var nameBytes = Encoding.UTF8.GetBytes(style.ToString() + "\0"); + Marshal.Copy(nameBytes, 0, (IntPtr)font.ConfigData.Name.Data, Math.Min(nameBytes.Length, font.ConfigData.Name.Count)); foreach (var (c, (rectId, glyph)) in this.glyphRectIds[style]) { var rc = ioFonts.GetCustomRectByIndex(rectId); var sourceBuffer = this.texturePixels[glyph.TextureFileIndex]; var sourceBufferDelta = glyph.TextureChannelByteIndex; - var widthAdjustment = style.CalculateWidthAdjustment(fdt, glyph); + var widthAdjustment = style.CalculateBaseWidthAdjustment(fdt, glyph); if (widthAdjustment == 0) { for (var y = 0; y < glyph.BoundingHeight; y++) @@ -401,10 +404,10 @@ namespace Dalamud.Interface.GameFonts for (var y = 0; y < glyph.BoundingHeight; y++) { float xDelta = xbold; - if (style.SkewStrength > 0) - xDelta += style.SkewStrength * (fdt.FontHeader.LineHeight - glyph.CurrentOffsetY - y) / fdt.FontHeader.LineHeight; - else if (style.SkewStrength < 0) - xDelta -= style.SkewStrength * (glyph.CurrentOffsetY + y) / fdt.FontHeader.LineHeight; + if (style.BaseSkewStrength > 0) + xDelta += style.BaseSkewStrength * (fdt.FontHeader.LineHeight - glyph.CurrentOffsetY - y) / fdt.FontHeader.LineHeight; + else if (style.BaseSkewStrength < 0) + xDelta -= style.BaseSkewStrength * (glyph.CurrentOffsetY + y) / fdt.FontHeader.LineHeight; var xDeltaInt = (int)Math.Floor(xDelta); var xness = xDelta - xDeltaInt; for (var x = 0; x < glyph.BoundingWidth; x++) @@ -433,11 +436,9 @@ namespace Dalamud.Interface.GameFonts } } } - } - foreach (var font in this.fonts.Values) - { CopyGlyphsAcrossFonts(InterfaceManager.DefaultFont, font, true, false); + UnscaleFont(font, 1 / scale, false); font.BuildLookupTable(); } } diff --git a/Dalamud/Interface/GameFonts/GameFontStyle.cs b/Dalamud/Interface/GameFonts/GameFontStyle.cs index 8636f128e..bd3a378f3 100644 --- a/Dalamud/Interface/GameFonts/GameFontStyle.cs +++ b/Dalamud/Interface/GameFonts/GameFontStyle.cs @@ -16,6 +16,11 @@ namespace Dalamud.Interface.GameFonts /// public GameFontFamilyAndSize FamilyAndSize; + /// + /// Size of the font in pixels unit. + /// + public float SizePx; + /// /// Weight of the font. /// @@ -37,11 +42,12 @@ namespace Dalamud.Interface.GameFonts /// Initializes a new instance of the struct. /// /// Font family. - /// Size in points. - public GameFontStyle(GameFontFamily family, float size) + /// Size in pixels. + public GameFontStyle(GameFontFamily family, float sizePx) { - this.FamilyAndSize = GetRecommendedFamilyAndSize(family, size); + this.FamilyAndSize = GetRecommendedFamilyAndSize(family, sizePx * 3 / 4); this.Weight = this.SkewStrength = 0f; + this.SizePx = sizePx; } /// @@ -52,6 +58,29 @@ namespace Dalamud.Interface.GameFonts { this.FamilyAndSize = familyAndSize; this.Weight = this.SkewStrength = 0f; + + // Dummy assignment to satisfy requirements + this.SizePx = 0; + + this.SizePx = this.BaseSizePx; + } + + /// + /// Gets or sets the size of the font in points unit. + /// + public float SizePt + { + get => this.SizePx * 3 / 4; + set => this.SizePx = value * 4 / 3; + } + + /// + /// Gets or sets the base skew strength. + /// + public float BaseSkewStrength + { + get => this.SkewStrength * this.BaseSizePx / this.SizePx; + set => this.SkewStrength = value * this.SizePx / this.BaseSizePx; } /// @@ -87,9 +116,23 @@ namespace Dalamud.Interface.GameFonts }; /// - /// Gets the font size in point unit. + /// Gets the corresponding GameFontFamilyAndSize but with minimum possible font sizes. /// - public float SizePt => this.FamilyAndSize switch + public GameFontFamilyAndSize FamilyWithMinimumSize => this.Family switch + { + GameFontFamily.Axis => GameFontFamilyAndSize.Axis96, + GameFontFamily.Jupiter => GameFontFamilyAndSize.Jupiter16, + GameFontFamily.JupiterNumeric => GameFontFamilyAndSize.Jupiter45, + GameFontFamily.Meidinger => GameFontFamilyAndSize.Meidinger16, + GameFontFamily.MiedingerMid => GameFontFamilyAndSize.MiedingerMid10, + GameFontFamily.TrumpGothic => GameFontFamilyAndSize.TrumpGothic184, + _ => GameFontFamilyAndSize.Undefined, + }; + + /// + /// Gets the base font size in point unit. + /// + public float BaseSizePt => this.FamilyAndSize switch { GameFontFamilyAndSize.Undefined => 0, GameFontFamilyAndSize.Axis96 => 9.6f, @@ -119,9 +162,9 @@ namespace Dalamud.Interface.GameFonts }; /// - /// Gets the font size in pixel unit. + /// Gets the base font size in pixel unit. /// - public float SizePx => this.SizePt * 4 / 3; + public float BaseSizePx => this.BaseSizePt * 4 / 3; /// /// Gets or sets a value indicating whether this font is bold. @@ -138,7 +181,7 @@ namespace Dalamud.Interface.GameFonts public bool Italic { get => this.SkewStrength != 0; - set => this.SkewStrength = value ? 4 : 0; + set => this.SkewStrength = value ? this.SizePx / 7 : 0; } /// @@ -226,15 +269,21 @@ namespace Dalamud.Interface.GameFonts /// Font information. /// Glyph. /// Width adjustment in pixel unit. - public int CalculateWidthAdjustment(FdtReader reader, FdtReader.FontTableEntry glyph) + public int CalculateBaseWidthAdjustment(FdtReader reader, FdtReader.FontTableEntry glyph) { var widthDelta = this.Weight; - if (this.SkewStrength > 0) - widthDelta += 1f * this.SkewStrength * (reader.FontHeader.LineHeight - glyph.CurrentOffsetY) / reader.FontHeader.LineHeight; - else if (this.SkewStrength < 0) - widthDelta -= 1f * this.SkewStrength * (glyph.CurrentOffsetY + glyph.BoundingHeight) / reader.FontHeader.LineHeight; + if (this.BaseSkewStrength > 0) + widthDelta += 1f * this.BaseSkewStrength * (reader.FontHeader.LineHeight - glyph.CurrentOffsetY) / reader.FontHeader.LineHeight; + else if (this.BaseSkewStrength < 0) + widthDelta -= 1f * this.BaseSkewStrength * (glyph.CurrentOffsetY + glyph.BoundingHeight) / reader.FontHeader.LineHeight; return (int)Math.Ceiling(widthDelta); } + + /// + public override string ToString() + { + return $"GameFontStyle({this.FamilyAndSize}, {this.SizePt}pt, skew={this.SkewStrength}, weight={this.Weight})"; + } } } diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 10e8309c4..cf87734a3 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -625,7 +625,7 @@ namespace Dalamud.Interface.Internal this.Axis = axis; this.TargetSizePx = sizePx; this.Scale = scale; - this.SourceAxis = Service.Get().NewFontRef(new(GameFontFamily.Axis, sizePx * scale * 3 / 4)); + this.SourceAxis = Service.Get().NewFontRef(new(GameFontFamily.Axis, sizePx * scale)); } internal enum AxisMode @@ -705,7 +705,7 @@ namespace Dalamud.Interface.Internal 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); + Log.Verbose("[FONT] SetupFonts - Default corresponding AXIS size: {0}pt ({1}px)", fontInfo.SourceAxis.Style.BaseSizePt, fontInfo.SourceAxis.Style.BaseSizePx); if (this.UseAxis) { fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); @@ -807,7 +807,7 @@ namespace Dalamud.Interface.Internal if (this.UseAxis) { fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); - fontConfig.SizePixels = fontInfo.SourceAxis.Style.SizePx; + fontConfig.SizePixels = fontInfo.SourceAxis.Style.BaseSizePx; fontConfig.PixelSnapH = false; var sizedFont = ioFonts.AddFontDefault(fontConfig); @@ -829,7 +829,7 @@ namespace Dalamud.Interface.Internal } } - gameFontManager.BuildFonts(); + gameFontManager.BuildFonts(disableBigFonts); var customFontFirstConfigIndex = ioFonts.ConfigData.Size; @@ -903,7 +903,7 @@ namespace Dalamud.Interface.Internal texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); } - gameFontManager.AfterBuildFonts(); + gameFontManager.AfterBuildFonts(disableBigFonts); foreach (var (font, mod) in this.loadedFontInfo) {