Fix adding supplemental language fonts for GamePrebakedFontHandle

This commit is contained in:
Soreepeong 2023-12-10 15:25:12 +09:00
parent e7c7cdaa29
commit 77536429d6
4 changed files with 55 additions and 13 deletions

View file

@ -1,7 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using ImGuiNET;
namespace Dalamud.Interface.ManagedFontAtlas; namespace Dalamud.Interface.ManagedFontAtlas;
/// <summary> /// <summary>
@ -58,6 +61,25 @@ public static class FontAtlasBuildToolkitUtilities
bool addEllipsisCodepoints = true) => bool addEllipsisCodepoints = true) =>
@string.AsSpan().ToGlyphRange(addFallbackCodepoints, addEllipsisCodepoints); @string.AsSpan().ToGlyphRange(addFallbackCodepoints, addEllipsisCodepoints);
/// <summary>
/// Finds the corresponding <see cref="ImFontConfigPtr"/> in
/// <see cref="IFontAtlasBuildToolkit.NewImAtlas"/>.<see cref="ImFontAtlasPtr.ConfigData"/> that corresponds to the
/// specified font <paramref name="fontPtr"/>.
/// </summary>
/// <param name="toolkit">The toolkit.</param>
/// <param name="fontPtr">The font.</param>
/// <returns>The relevant config pointer, or empty config pointer if not found.</returns>
public static unsafe ImFontConfigPtr FindConfigPtr(this IFontAtlasBuildToolkit toolkit, ImFontPtr fontPtr)
{
foreach (ref var c in toolkit.NewImAtlas.ConfigDataWrapped().DataSpan)
{
if (c.DstFont == fontPtr.NativePtr)
return new((nint)Unsafe.AsPointer(ref c));
}
return default;
}
/// <summary> /// <summary>
/// Invokes <paramref name="action"/> /// Invokes <paramref name="action"/>
/// if <see cref="IFontAtlasBuildToolkit.BuildStep"/> of <paramref name="toolkit"/> /// if <see cref="IFontAtlasBuildToolkit.BuildStep"/> of <paramref name="toolkit"/>

View file

@ -204,7 +204,6 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
internal sealed class HandleSubstance : IFontHandleSubstance internal sealed class HandleSubstance : IFontHandleSubstance
{ {
private readonly HandleManager handleManager; private readonly HandleManager handleManager;
private readonly InterfaceManager interfaceManager;
private readonly HashSet<GameFontStyle> gameFontStyles; private readonly HashSet<GameFontStyle> gameFontStyles;
// Owned by this class, but ImFontPtr values still do not belong to this. // Owned by this class, but ImFontPtr values still do not belong to this.
@ -226,7 +225,7 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
public HandleSubstance(HandleManager manager, IEnumerable<GameFontStyle> gameFontStyles) public HandleSubstance(HandleManager manager, IEnumerable<GameFontStyle> gameFontStyles)
{ {
this.handleManager = manager; this.handleManager = manager;
this.interfaceManager = Service<InterfaceManager>.Get(); Service<InterfaceManager>.Get();
this.gameFontStyles = new(gameFontStyles); this.gameFontStyles = new(gameFontStyles);
} }
@ -351,20 +350,21 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
var fdtGlyphs = fdt.Glyphs; var fdtGlyphs = fdt.Glyphs;
var fontPtr = font.NativePtr; var fontPtr = font.NativePtr;
fontPtr->FontSize = (fdtFontHeader.Size * 4) / 3; var glyphs = font.GlyphsWrapped();
var scale = toolkitPostBuild.Scale * (style.SizePt / fdtFontHeader.Size);
fontPtr->FontSize = toolkitPostBuild.Scale * style.SizePx;
if (fontPtr->ConfigData != null) if (fontPtr->ConfigData != null)
fontPtr->ConfigData->SizePixels = fontPtr->FontSize; fontPtr->ConfigData->SizePixels = fontPtr->FontSize;
fontPtr->Ascent = fdtFontHeader.Ascent; fontPtr->Ascent = fdtFontHeader.Ascent * scale;
fontPtr->Descent = fdtFontHeader.Descent; fontPtr->Descent = fdtFontHeader.Descent * scale;
fontPtr->EllipsisChar = '…'; fontPtr->EllipsisChar = '…';
if (!allTexFiles.TryGetValue(attr.TexPathFormat, out var texFiles)) if (!allTexFiles.TryGetValue(attr.TexPathFormat, out var texFiles))
allTexFiles.Add(attr.TexPathFormat, texFiles = ArrayPool<TexFile>.Shared.Rent(texCount)); allTexFiles.Add(attr.TexPathFormat, texFiles = ArrayPool<TexFile>.Shared.Rent(texCount));
if (this.glyphRectIds.TryGetValue(style, out var rectIdToGlyphs)) if (this.glyphRectIds.TryGetValue(style, out var rectIdToGlyphs))
{ {
this.glyphRectIds.Remove(style);
foreach (var (rectId, fdtGlyphIndex) in rectIdToGlyphs.Values) foreach (var (rectId, fdtGlyphIndex) in rectIdToGlyphs.Values)
{ {
ref var glyph = ref fdtGlyphs[fdtGlyphIndex]; ref var glyph = ref fdtGlyphs[fdtGlyphIndex];
@ -442,6 +442,9 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
} }
} }
} }
glyphs[rc->GlyphId].XY *= scale;
glyphs[rc->GlyphId].AdvanceX *= scale;
} }
} }
else if (this.lateBuildRanges.TryGetValue(font, out var buildRanges)) else if (this.lateBuildRanges.TryGetValue(font, out var buildRanges))
@ -480,7 +483,6 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
textureIndices.AsSpan(0, texCount).Fill(-1); textureIndices.AsSpan(0, texCount).Fill(-1);
} }
var glyphs = font.GlyphsWrapped();
glyphs.EnsureCapacity(glyphs.Length + buildRanges.Sum(x => (x.To - x.From) + 1)); glyphs.EnsureCapacity(glyphs.Length + buildRanges.Sum(x => (x.To - x.From) + 1));
foreach (var (rangeMin, rangeMax) in buildRanges) foreach (var (rangeMin, rangeMax) in buildRanges)
{ {
@ -530,6 +532,8 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
glyph.XY1 = glyph.XY0 + glyph.UV1; glyph.XY1 = glyph.XY0 + glyph.UV1;
glyph.UV1 += glyph.UV0; glyph.UV1 += glyph.UV0;
glyph.UV /= fdtTexSize; glyph.UV /= fdtTexSize;
glyph.XY *= scale;
glyph.AdvanceX *= scale;
glyphs.Add(glyph); glyphs.Add(glyph);
} }
@ -555,7 +559,7 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
} }
} }
font.AdjustGlyphMetrics(style.SizePt / fdtFontHeader.Size, toolkitPostBuild.Scale); font.AdjustGlyphMetrics(1 / toolkitPostBuild.Scale, toolkitPostBuild.Scale);
} }
catch (Exception e) catch (Exception e)
{ {
@ -616,7 +620,10 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
var font = toolkitPreBuild.IgnoreGlobalScale(this.CreateTemplateFont(style, toolkitPreBuild)); var font = toolkitPreBuild.IgnoreGlobalScale(this.CreateTemplateFont(style, toolkitPreBuild));
if (addExtraLanguageGlyphs) if (addExtraLanguageGlyphs)
toolkitPreBuild.AddExtraGlyphsForDalamudLanguage(new() { MergeFont = font }); {
toolkitPreBuild.AddExtraGlyphsForDalamudLanguage(
new(toolkitPreBuild.FindConfigPtr(font)) { MergeFont = font });
}
var fas = GameFontStyle.GetRecommendedFamilyAndSize(style.Family, style.SizePt * toolkitPreBuild.Scale); var fas = GameFontStyle.GetRecommendedFamilyAndSize(style.Family, style.SizePt * toolkitPreBuild.Scale);
var horizontalOffset = fas.GetAttribute<GameFontFamilyAndSizeAttribute>()?.HorizontalOffset ?? 0; var horizontalOffset = fas.GetAttribute<GameFontFamilyAndSizeAttribute>()?.HorizontalOffset ?? 0;
@ -662,9 +669,10 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
fdtGlyphIndex); fdtGlyphIndex);
} }
} }
var scale = toolkitPreBuild.Scale * (style.SizePt / fdt.FontHeader.Size);
foreach (ref var kernPair in fdt.PairAdjustments) foreach (ref var kernPair in fdt.PairAdjustments)
font.AddKerningPair(kernPair.Left, kernPair.Right, kernPair.RightOffset); font.AddKerningPair(kernPair.Left, kernPair.Right, kernPair.RightOffset * scale);
return font; return font;
} }

View file

@ -31,6 +31,17 @@ public struct SafeFontConfig
this.Raw.FontDataOwnedByAtlas = 1; this.Raw.FontDataOwnedByAtlas = 1;
} }
/// <summary>
/// Initializes a new instance of the <see cref="SafeFontConfig"/> struct,
/// copying applicable values from an existing instance of <see cref="ImFontConfigPtr"/>.
/// </summary>
/// <param name="config">Config to copy from.</param>
public unsafe SafeFontConfig(ImFontConfigPtr config)
{
this.Raw = *config.NativePtr;
this.Raw.GlyphRanges = null;
}
/// <summary> /// <summary>
/// Gets or sets the index of font within a TTF/OTF file. /// Gets or sets the index of font within a TTF/OTF file.
/// </summary> /// </summary>

View file

@ -525,6 +525,7 @@ public static class ImGuiHelpers
(ushort)Math.Min(x.FirstCodePoint, ushort.MaxValue), (ushort)Math.Min(x.FirstCodePoint, ushort.MaxValue),
(ushort)Math.Min(x.FirstCodePoint + x.Length, ushort.MaxValue), (ushort)Math.Min(x.FirstCodePoint + x.Length, ushort.MaxValue),
}) })
.Append((ushort)0)
.ToArray(); .ToArray();
/// <summary> /// <summary>