From a2394cc044aaaf61d6b36097ec5ec1205e044e28 Mon Sep 17 00:00:00 2001 From: Argi <15852038+argium@users.noreply.github.com> Date: Mon, 6 Jul 2026 10:24:31 +1000 Subject: [PATCH] Make font application lazy Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- FrameUtil.lua | 57 +++++++++++++++++++++++++++++++++++++--- Tests/Utilities_spec.lua | 12 +++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/FrameUtil.lua b/FrameUtil.lua index 377f8195..379e316f 100644 --- a/FrameUtil.lua +++ b/FrameUtil.lua @@ -570,6 +570,44 @@ local function getLsmMedia(mediaType, key) end end +local function fontMatches(fontString, fontPath, fontSize, fontOutline) + if fontString.GetFont then + local livePath, liveSize, liveOutline = fontString:GetFont() + if livePath ~= nil then + return livePath == fontPath + and ns.NumericEquals(liveSize, fontSize) + and (liveOutline or "") == fontOutline + end + end + + return fontString.__ecmFontPath == fontPath + and ns.NumericEquals(fontString.__ecmFontSize, fontSize) + and fontString.__ecmFontOutline == fontOutline +end + +local function shadowMatches(fontString, hasShadow, offsetX, offsetY) + if fontString.GetShadowOffset then + local liveX, liveY = fontString:GetShadowOffset() + if not ns.NumericEquals(liveX, offsetX) or not ns.NumericEquals(liveY, offsetY) then + return false + end + + if hasShadow and fontString.GetShadowColor then + local r, g, b, a = fontString:GetShadowColor() + return ns.NumericEquals(r, 0) + and ns.NumericEquals(g, 0) + and ns.NumericEquals(b, 0) + and ns.NumericEquals(a, 1) + end + + return true + end + + return fontString.__ecmFontShadow == hasShadow + and ns.NumericEquals(fontString.__ecmFontShadowOffsetX, offsetX) + and ns.NumericEquals(fontString.__ecmFontShadowOffsetY, offsetY) +end + function FrameUtil.GetTexture(texture) local fetched = texture and getLsmMedia("statusbar", texture) if fetched then return fetched end @@ -597,14 +635,25 @@ function FrameUtil.ApplyFont(fontString, globalConfig, moduleConfig) ns.DebugAssert(fontSize, "Font size cannot be nil") ns.DebugAssert(fontOutline, "Font outline cannot be nil") - fontString:SetFont(fontPath, fontSize, fontOutline) + if not fontMatches(fontString, fontPath, fontSize, fontOutline) then + fontString:SetFont(fontPath, fontSize, fontOutline) + fontString.__ecmFontPath = fontPath + fontString.__ecmFontSize = fontSize + fontString.__ecmFontOutline = fontOutline + end + local shadowOffsetX = hasShadow and 1 or 0 + local shadowOffsetY = hasShadow and -1 or 0 + if shadowMatches(fontString, hasShadow, shadowOffsetX, shadowOffsetY) then + return + end if hasShadow then fontString:SetShadowColor(0, 0, 0, 1) - fontString:SetShadowOffset(1, -1) - else - fontString:SetShadowOffset(0, 0) end + fontString:SetShadowOffset(shadowOffsetX, shadowOffsetY) + fontString.__ecmFontShadow = hasShadow + fontString.__ecmFontShadowOffsetX = shadowOffsetX + fontString.__ecmFontShadowOffsetY = shadowOffsetY end function FrameUtil.PixelSnap(v) diff --git a/Tests/Utilities_spec.lua b/Tests/Utilities_spec.lua index c9e62b8a..41b377f4 100644 --- a/Tests/Utilities_spec.lua +++ b/Tests/Utilities_spec.lua @@ -195,4 +195,16 @@ describe("Utilities", function() assert.are.equal("FONT:DB Global Font", call.path) assert.are.equal(15, call.size) end) + + it("ECM.ApplyFont skips repeated setter calls when font settings are unchanged", function() + local fontString = newFontStringSpy() + local globalConfig = ns.Addon.db.profile.global + + ns.FrameUtil.ApplyFont(fontString, globalConfig, { overrideFont = false }) + ns.FrameUtil.ApplyFont(fontString, globalConfig, { overrideFont = false }) + + assert.are.equal(1, #fontString.setFontCalls) + assert.are.equal(1, #fontString.shadowOffsetCalls) + assert.are.equal(0, #fontString.shadowColorCalls) + end) end)