diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs index 46fb3f63d..fdef499dd 100644 --- a/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs +++ b/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs @@ -430,7 +430,7 @@ internal sealed partial class FontAtlasFactory foreach (ref var font in this.Fonts.DataSpan) { if (!this.GlobalScaleExclusions.Contains(font)) - font.AdjustGlyphMetrics(1 / scale, scale); + font.AdjustGlyphMetrics(1 / scale, 1 / scale); foreach (var c in FallbackCodepoints) { diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs index 1ac6fdbce..99c817a91 100644 --- a/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs +++ b/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs @@ -369,8 +369,8 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal this.PatchFontMetricsIfNecessary(style, font, toolkitPostBuild.Scale); plan.SetFullRangeFontGlyphs(toolkitPostBuild, allTexFiles, allTextureIndices, pixels8Array, widths); - plan.PostProcessFullRangeFont(); - plan.CopyGlyphsToRanges(); + plan.CopyGlyphsToRanges(toolkitPostBuild); + plan.PostProcessFullRangeFont(toolkitPostBuild.Scale); } catch (Exception e) { @@ -543,17 +543,43 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal } } - public unsafe void PostProcessFullRangeFont() + public unsafe void PostProcessFullRangeFont(float atlasScale) { + var round = 1 / atlasScale; + var pfrf = this.FullRangeFont.NativePtr; + ref var frf = ref *pfrf; + + frf.FontSize = MathF.Round(frf.FontSize / round) * round; + frf.Ascent = MathF.Round(frf.Ascent / round) * round; + frf.Descent = MathF.Round(frf.Descent / round) * round; + var scale = this.Style.SizePt / this.Fdt.FontHeader.Size; foreach (ref var g in this.FullRangeFont.GlyphsWrapped().DataSpan) { - g.XY *= scale; - g.AdvanceX *= scale; + var w = (g.X1 - g.X0) * scale; + var h = (g.Y1 - g.Y0) * scale; + g.X0 = MathF.Round((g.X0 * scale) / round) * round; + g.Y0 = MathF.Round((g.Y0 * scale) / round) * round; + g.X1 = g.X0 + w; + g.Y1 = g.Y0 + h; + g.AdvanceX = MathF.Round((g.AdvanceX * scale) / round) * round; + } + + var fullRange = this.Ranges[this.FullRangeFont]; + foreach (ref var k in this.Fdt.PairAdjustments) + { + var (leftInt, rightInt) = (k.LeftInt, k.RightInt); + if (leftInt > char.MaxValue || rightInt > char.MaxValue) + continue; + if (!fullRange[leftInt] || !fullRange[rightInt]) + continue; + ImGuiNative.ImFont_AddKerningPair( + pfrf, + (ushort)leftInt, + (ushort)rightInt, + MathF.Round((k.RightOffset * scale) / round) * round); } - var pfrf = this.FullRangeFont.NativePtr; - ref var frf = ref *pfrf; pfrf->FallbackGlyph = null; ImGuiNative.ImFont_BuildLookupTable(pfrf); @@ -571,13 +597,19 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal } } - public unsafe void CopyGlyphsToRanges() + public unsafe void CopyGlyphsToRanges(IFontAtlasBuildToolkitPostBuild toolkitPostBuild) { + var scale = this.Style.SizePt / this.Fdt.FontHeader.Size; + var atlasScale = toolkitPostBuild.Scale; + var round = 1 / atlasScale; + foreach (var (font, rangeBits) in this.Ranges) { if (font.NativePtr == this.FullRangeFont.NativePtr) continue; + var noGlobalScale = toolkitPostBuild.IsGlobalScaleIgnored(font); + var lookup = font.IndexLookupWrapped(); var glyphs = font.GlyphsWrapped(); foreach (ref var sourceGlyph in this.FullRangeFont.GlyphsWrapped().DataSpan) @@ -590,9 +622,48 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal glyphIndex = lookup[sourceGlyph.Codepoint]; if (glyphIndex == ushort.MaxValue) - glyphs.Add(sourceGlyph); + { + glyphIndex = (ushort)glyphs.Length; + glyphs.Add(default); + } + + ref var g = ref glyphs[glyphIndex]; + g = sourceGlyph; + if (noGlobalScale) + { + g.XY *= scale; + g.AdvanceX *= scale; + } else - glyphs[glyphIndex] = sourceGlyph; + { + var w = (g.X1 - g.X0) * scale; + var h = (g.Y1 - g.Y0) * scale; + g.X0 = MathF.Round((g.X0 * scale) / round) * round; + g.Y0 = MathF.Round((g.Y0 * scale) / round) * round; + g.X1 = g.X0 + w; + g.Y1 = g.Y0 + h; + g.AdvanceX = MathF.Round((g.AdvanceX * scale) / round) * round; + } + } + + foreach (ref var k in this.Fdt.PairAdjustments) + { + var (leftInt, rightInt) = (k.LeftInt, k.RightInt); + if (leftInt > char.MaxValue || rightInt > char.MaxValue) + continue; + if (!rangeBits[leftInt] || !rangeBits[rightInt]) + continue; + if (noGlobalScale) + { + font.AddKerningPair((ushort)leftInt, (ushort)rightInt, k.RightOffset * scale); + } + else + { + font.AddKerningPair( + (ushort)leftInt, + (ushort)rightInt, + MathF.Round((k.RightOffset * scale) / round) * round); + } } font.NativePtr->FallbackGlyph = null; diff --git a/Dalamud/Interface/Utility/ImGuiHelpers.cs b/Dalamud/Interface/Utility/ImGuiHelpers.cs index ed6ad1dfe..8ba103593 100644 --- a/Dalamud/Interface/Utility/ImGuiHelpers.cs +++ b/Dalamud/Interface/Utility/ImGuiHelpers.cs @@ -202,7 +202,7 @@ public static class ImGuiHelpers /// If a positive number is given, numbers will be rounded to this. public static unsafe void AdjustGlyphMetrics(this ImFontPtr fontPtr, float scale, float round = 0f) { - Func rounder = round > 0 ? x => MathF.Round(x * round) / round : x => x; + Func rounder = round > 0 ? x => MathF.Round(x / round) * round : x => x; var font = fontPtr.NativePtr; font->FontSize = rounder(font->FontSize * scale);