Two roles need a face of their own, and they need it for opposite reasons. The sender is meant to carry weight. The mockup says 600, and there is no bold face anywhere in the plugin -- the bundled file is Inter-Light and the game's Axis is a single weight. So the weight comes from rasterising the same outline denser, via RasterizerMultiply. That only works on the delegate path: with both font toggles off the game font handle draws and has no such knob, and the sender falls back to leaning on channel colour alone. Deliberate limitation, not an oversight. The meta face goes the other way: smaller, and on a glyph range of about eighty entries instead of the full set. Timestamps and world names are Latin in every client FFXIV ships, so ASCII plus the middle dot covers what this face will ever be asked to draw. A full range would have rasterised the whole CJK block a second time for nothing. Anything translated stays on the body face. Two things in the rebuild path had to change with them. The handles now go up inside a SuppressAutoRebuild block -- without it, one size change meant four separate atlas rebuilds instead of one. And FontsReady checks both new handles unconditionally, unlike ItalicFont which is allowed to be null: a handle that is not ready makes SimplePushedFont push nothing at all, silently, and the first frame after a rebuild would measure the wrong face and write those heights into the row cache. Both font self-tests were extended to match. A handle nobody asserts is a handle that can go missing for a release without anyone noticing.
55 lines
1.6 KiB
C#
55 lines
1.6 KiB
C#
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Plugin.SelfTest;
|
|
|
|
namespace HellionChat.SelfTests;
|
|
|
|
// Push-safety smoke: IFontHandle.Push() is contracted safe regardless
|
|
// of the Available state, so this step proves the ctor-built handles
|
|
// can be pushed even right after plugin load. Self-test steps run on
|
|
// the framework thread via the xlperf path, so the push call itself
|
|
// stays main-thread-safe.
|
|
internal sealed class FontPushSmokeStep : ISelfTestStep
|
|
{
|
|
private readonly Plugin plugin;
|
|
|
|
public FontPushSmokeStep(Plugin plugin)
|
|
{
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
public string Name => "Hellion Chat - FontManager push smoke";
|
|
|
|
public SelfTestStepResult RunStep()
|
|
{
|
|
var fm = this.plugin.FontManager;
|
|
if (fm?.RegularFont is null || fm.FontAwesome is null)
|
|
{
|
|
ImGui.Text("RegularFont or FontAwesome missing - see FontManager ctor smoke");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
if (fm.SenderFont is null || fm.MetaFont is null)
|
|
{
|
|
ImGui.Text("SenderFont or MetaFont missing - see FontManager ctor smoke");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
try
|
|
{
|
|
using (fm.RegularFont.Push()) { }
|
|
using (fm.FontAwesome.Push()) { }
|
|
using (fm.SenderFont.Push()) { }
|
|
using (fm.MetaFont.Push()) { }
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
ImGui.Text($"Push threw: {e.GetType().Name}: {e.Message}");
|
|
return SelfTestStepResult.Fail;
|
|
}
|
|
|
|
return SelfTestStepResult.Pass;
|
|
}
|
|
|
|
public void CleanUp() { }
|
|
}
|