diff --git a/HellionChat/FontManager.cs b/HellionChat/FontManager.cs index 86d9495..79fcb6a 100644 --- a/HellionChat/FontManager.cs +++ b/HellionChat/FontManager.cs @@ -59,7 +59,7 @@ public sealed class FontManager : IDisposable private Func? _typographySource; // Lets RebuildDelegateFontsIfChanged skip rebuilds when the size is unchanged. - private (float Global, float Symbols) _lastBuiltFingerprint; + private (float Global, float Symbols, float Sender, float Meta, float Italic) _lastBuiltFingerprint; // True once every required atlas-owned handle reports Available. Components // gate their first-frame draw on this — without it the layout math would @@ -216,8 +216,21 @@ public sealed class FontManager : IDisposable Plugin.Config.SymbolsFontSizeV2 ); - internal (float Global, float Symbols) EffectiveFontFingerprint() => - (ResolveGlobalFontPt(), ResolveSymbolsFontPt()); + // Every size that can land in one message row. Roles follow the base size + // arithmetically, but the resolved value is what the height cache has to key + // on -- a theme override moves the base without moving any factor. + internal (float Global, float Symbols, float Sender, float Meta, float Italic) + EffectiveFontFingerprint() + { + var basePt = ResolveGlobalFontPt(); + return ( + basePt, + ResolveSymbolsFontPt(), + TypeScale.SizePtOf(TypeRole.Sender, basePt), + TypeScale.SizePtOf(TypeRole.Meta, basePt), + Plugin.Config.ItalicFontV2.SizePt + ); + } // Rebuilds only when the effective size changed (live fingerprint, TOCTOU-free). // The atlas rebuild must run on the framework/draw thread — callers ensure that. diff --git a/HellionChat/Ui/Components/MessageList.cs b/HellionChat/Ui/Components/MessageList.cs index e9fc90a..6024736 100644 --- a/HellionChat/Ui/Components/MessageList.cs +++ b/HellionChat/Ui/Components/MessageList.cs @@ -93,13 +93,25 @@ internal sealed class MessageList // Width is passed in (ContentRegionAvail is only valid inside the draw child); // enum modes widened to int so the record stays comparable. UiScale is in here // because it feeds CalcWordWrapPositionA -- a scale change rewraps every row. + // + // v1.13.0 added four axes that could always stale this cache and never did: + // the italic size (pushed mid-row by ChunkRenderer), ItalicEnabled (which + // swaps between two differently sized faces), FontsEnabled and UseHellionFont + // (both swap the face outright, and their two size fields default to the same + // 12.75f -- so the fingerprint did not move while the glyph widths did). private LayoutFingerprint BuildLayoutFingerprint(float contentWidth) { - var (global, symbols) = _fonts.EffectiveFontFingerprint(); + var fonts = _fonts.EffectiveFontFingerprint(); return new LayoutFingerprint( - global, - symbols, + fonts.Global, + fonts.Symbols, + fonts.Sender, + fonts.Meta, + fonts.Italic, Plugin.Config.UseCompactDensity, + Plugin.Config.FontsEnabled, + Plugin.Config.UseHellionFont, + Plugin.Config.ItalicEnabled, (int)Plugin.Config.NameFormMode, (int)Plugin.Config.WorldSuffixMode, contentWidth, diff --git a/HellionChat/Util/LayoutFingerprint.cs b/HellionChat/Util/LayoutFingerprint.cs index f6c6785..be2db40 100644 --- a/HellionChat/Util/LayoutFingerprint.cs +++ b/HellionChat/Util/LayoutFingerprint.cs @@ -5,7 +5,13 @@ namespace HellionChat.Util; internal readonly record struct LayoutFingerprint( float FontGlobal, float FontSymbols, + float FontSender, + float FontMeta, + float FontItalic, bool Compact, + bool FontsEnabled, + bool UseHellionFont, + bool ItalicEnabled, int NameForm, int WorldSuffix, float Width, @@ -15,7 +21,8 @@ internal readonly record struct LayoutFingerprint( // Toggles: they land on a new value in one frame and stay there. Waiting on // them would leave the planner running against the previous density's // heights while the rows are already painted the new way. - internal (bool, int, int) Discrete => (Compact, NameForm, WorldSuffix); + internal (bool, bool, bool, bool, int, int) Discrete => + (Compact, FontsEnabled, UseHellionFont, ItalicEnabled, NameForm, WorldSuffix); } // Dragging a window edge or the Dalamud UI-scale slider moves the continuous