blur uses radius instead of intensity

This commit is contained in:
Michael Freno
2025-12-05 11:31:52 -05:00
parent 3eb5b12240
commit 7883f914d9
11 changed files with 136 additions and 144 deletions

View File

@@ -511,7 +511,7 @@ function flexlove.draw(gameDrawFunc, postDrawFunc)
end) end)
local function hasBackdropBlur(element) local function hasBackdropBlur(element)
if element.backdropBlur and element.backdropBlur.intensity > 0 then if element.backdropBlur and element.backdropBlur.radius > 0 then
return true return true
end end
for _, child in ipairs(element.children) do for _, child in ipairs(element.children) do

View File

@@ -377,10 +377,11 @@ end</code></pre>
<div class="note"> <div class="note">
<p> <p>
<strong>💡 Tip:</strong> Use <code>positioning = "grid"</code> with <strong>💡 Tip:</strong> Use <code>positioning = "grid"</code> with
<code>gridRows</code> and <code>gridColumns</code> to create true grid <code>gridRows</code> and <code>gridColumns</code> to create true
layouts. Children auto-flow into cells left-to-right, top-to-bottom. grid layouts. Children auto-flow into cells left-to-right,
Perfect for tables, schedules, and structured data displays. top-to-bottom. Perfect for tables, schedules, and structured data
displays.
</p> </p>
</div> </div>
@@ -589,7 +590,7 @@ local window = FlexLove.new({
positioning = "flex", positioning = "flex",
flexDirection = "vertical", flexDirection = "vertical",
gap = 10, gap = 10,
backdropBlur = { intensity = 50, quality = 10 }, backdropBlur = { radius = 10, quality = 10 },
backgroundColor = Color.new(0.1, 0.1, 0.1, 0.8) backgroundColor = Color.new(0.1, 0.1, 0.1, 0.8)
}) })
@@ -1088,32 +1089,32 @@ end</code></pre>
}); });
// Add copy buttons to code blocks // Add copy buttons to code blocks
document.querySelectorAll('pre code').forEach((codeBlock) => { document.querySelectorAll("pre code").forEach((codeBlock) => {
const pre = codeBlock.parentElement; const pre = codeBlock.parentElement;
const button = document.createElement('button'); const button = document.createElement("button");
button.className = 'copy-button'; button.className = "copy-button";
button.textContent = 'Copy'; button.textContent = "Copy";
button.title = 'Copy to clipboard'; button.title = "Copy to clipboard";
button.addEventListener('click', async () => { button.addEventListener("click", async () => {
const code = codeBlock.textContent; const code = codeBlock.textContent;
try { try {
await navigator.clipboard.writeText(code); await navigator.clipboard.writeText(code);
button.textContent = 'Copied!'; button.textContent = "Copied!";
button.classList.add('copied'); button.classList.add("copied");
setTimeout(() => { setTimeout(() => {
button.textContent = 'Copy'; button.textContent = "Copy";
button.classList.remove('copied'); button.classList.remove("copied");
}, 2000); }, 2000);
} catch (err) { } catch (err) {
console.error('Failed to copy:', err); console.error("Failed to copy:", err);
button.textContent = 'Failed'; button.textContent = "Failed";
setTimeout(() => { setTimeout(() => {
button.textContent = 'Copy'; button.textContent = "Copy";
}, 2000); }, 2000);
} }
}); });
pre.appendChild(button); pre.appendChild(button);
}); });
</script> </script>

View File

@@ -25,7 +25,7 @@ function ScrollableContentExample.new()
justifyContent = "center", justifyContent = "center",
alignItems = "center", alignItems = "center",
gap = 10, gap = 10,
backdropBlur = { intensity = 50, quality = 10 }, backdropBlur = { radius = 20, quality = 10 },
backgroundColor = Color.new(0.1, 0.1, 0.1, 0.8), backgroundColor = Color.new(0.1, 0.1, 0.1, 0.8),
}) })

View File

@@ -12,7 +12,7 @@ local Cache = {
MAX_CANVAS_SIZE = 20, MAX_CANVAS_SIZE = 20,
MAX_QUAD_SIZE = 20, MAX_QUAD_SIZE = 20,
MAX_BLURRED_CANVAS_CACHE = 50, -- Maximum cached blurred canvases MAX_BLURRED_CANVAS_CACHE = 50, -- Maximum cached blurred canvases
INTENSITY_THRESHOLD = 5, -- Skip blur below this intensity RADIUS_THRESHOLD = 0.5, -- Skip blur below this radius
LARGE_BLUR_THRESHOLD = 250 * 250, -- Warn if blur area exceeds this (250x250px) LARGE_BLUR_THRESHOLD = 250 * 250, -- Warn if blur area exceeds this (250x250px)
} }
@@ -133,12 +133,12 @@ end
---@param y number Y position ---@param y number Y position
---@param width number Width ---@param width number Width
---@param height number Height ---@param height number Height
---@param intensity number Blur intensity ---@param radius number Blur radius
---@param quality number Blur quality ---@param quality number Blur quality
---@param isBackdrop boolean Whether this is backdrop blur ---@param isBackdrop boolean Whether this is backdrop blur
---@return string key Cache key ---@return string key Cache key
function Cache.generateBlurCacheKey(elementId, x, y, width, height, intensity, quality, isBackdrop) function Cache.generateBlurCacheKey(elementId, x, y, width, height, radius, quality, isBackdrop)
return string.format("%s:%d:%d:%d:%d:%d:%d:%s", elementId, x, y, width, height, intensity, quality, tostring(isBackdrop)) return string.format("%s:%d:%d:%d:%d:%.1f:%d:%s", elementId, x, y, width, height, radius, quality, tostring(isBackdrop))
end end
--- Get cached blurred canvas --- Get cached blurred canvas
@@ -381,13 +381,13 @@ function Blur.new(props)
end end
--- Apply blur to a region of the screen --- Apply blur to a region of the screen
---@param intensity number Blur intensity (0-100) ---@param radius number Blur radius in pixels
---@param x number X position ---@param x number X position
---@param y number Y position ---@param y number Y position
---@param width number Width of region ---@param width number Width of region
---@param height number Height of region ---@param height number Height of region
---@param drawFunc function Function to draw content to be blurred ---@param drawFunc function Function to draw content to be blurred
function Blur:applyToRegion(intensity, x, y, width, height, drawFunc) function Blur:applyToRegion(radius, x, y, width, height, drawFunc)
if type(drawFunc) ~= "function" then if type(drawFunc) ~= "function" then
if Blur._ErrorHandler then if Blur._ErrorHandler then
Blur._ErrorHandler:warn("Blur", "BLUR_001") Blur._ErrorHandler:warn("Blur", "BLUR_001")
@@ -395,13 +395,13 @@ function Blur:applyToRegion(intensity, x, y, width, height, drawFunc)
return return
end end
if intensity <= 0 or width <= 0 or height <= 0 then if radius <= 0 or width <= 0 or height <= 0 then
drawFunc() drawFunc()
return return
end end
-- Early exit for very low intensity (optimization) -- Early exit for very low radius (optimization)
if intensity < Cache.INTENSITY_THRESHOLD then if radius < Cache.RADIUS_THRESHOLD then
drawFunc() drawFunc()
return return
end end
@@ -409,11 +409,9 @@ function Blur:applyToRegion(intensity, x, y, width, height, drawFunc)
-- Check for large blur area in immediate mode -- Check for large blur area in immediate mode
checkLargeBlurWarning(nil, width, height, "content") checkLargeBlurWarning(nil, width, height, "content")
intensity = math.max(0, math.min(100, intensity)) -- Calculate offset multiplier based on radius and quality
-- Higher quality = more samples = smaller steps for same radius
-- Intensity 0-100 maps to 0-5 passes local offsetMultiplier = radius / self.quality
local passes = math.ceil(intensity / 20)
passes = math.max(1, math.min(5, passes))
local canvas1 = Cache.getCanvas(width, height) local canvas1 = Cache.getCanvas(width, height)
local canvas2 = Cache.getCanvas(width, height) local canvas2 = Cache.getCanvas(width, height)
@@ -435,17 +433,16 @@ function Blur:applyToRegion(intensity, x, y, width, height, drawFunc)
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
love.graphics.setBlendMode("alpha", "premultiplied") love.graphics.setBlendMode("alpha", "premultiplied")
for i = 1, passes do -- Single pass with radius-controlled offset
love.graphics.setCanvas(canvas2) love.graphics.setCanvas(canvas2)
love.graphics.clear() love.graphics.clear()
self.shader:send("direction", { 1 / width, 0 }) self.shader:send("direction", { offsetMultiplier / width, 0 })
love.graphics.draw(canvas1, 0, 0) love.graphics.draw(canvas1, 0, 0)
love.graphics.setCanvas(canvas1) love.graphics.setCanvas(canvas1)
love.graphics.clear() love.graphics.clear()
self.shader:send("direction", { 0, 1 / height }) self.shader:send("direction", { 0, offsetMultiplier / height })
love.graphics.draw(canvas2, 0, 0) love.graphics.draw(canvas2, 0, 0)
end
love.graphics.setCanvas(prevCanvas) love.graphics.setCanvas(prevCanvas)
love.graphics.setShader() love.graphics.setShader()
@@ -460,13 +457,13 @@ function Blur:applyToRegion(intensity, x, y, width, height, drawFunc)
end end
--- Apply backdrop blur effect (blur content behind a region) --- Apply backdrop blur effect (blur content behind a region)
---@param intensity number Blur intensity (0-100) ---@param radius number Blur radius in pixels
---@param x number X position ---@param x number X position
---@param y number Y position ---@param y number Y position
---@param width number Width of region ---@param width number Width of region
---@param height number Height of region ---@param height number Height of region
---@param backdropCanvas love.Canvas Canvas containing the backdrop content ---@param backdropCanvas love.Canvas Canvas containing the backdrop content
function Blur:applyBackdrop(intensity, x, y, width, height, backdropCanvas) function Blur:applyBackdrop(radius, x, y, width, height, backdropCanvas)
if not backdropCanvas then if not backdropCanvas then
if Blur._ErrorHandler then if Blur._ErrorHandler then
Blur._ErrorHandler:warn("Blur", "BLUR_002") Blur._ErrorHandler:warn("Blur", "BLUR_002")
@@ -474,19 +471,17 @@ function Blur:applyBackdrop(intensity, x, y, width, height, backdropCanvas)
return return
end end
if intensity <= 0 or width <= 0 or height <= 0 then if radius <= 0 or width <= 0 or height <= 0 then
return return
end end
-- Early exit for very low intensity (optimization) -- Early exit for very low radius (optimization)
if intensity < Cache.INTENSITY_THRESHOLD then if radius < Cache.RADIUS_THRESHOLD then
return return
end end
intensity = math.max(0, math.min(100, intensity)) -- Calculate offset multiplier based on radius and quality
local offsetMultiplier = radius / self.quality
local passes = math.ceil(intensity / 20)
passes = math.max(1, math.min(5, passes))
local canvas1 = Cache.getCanvas(width, height) local canvas1 = Cache.getCanvas(width, height)
local canvas2 = Cache.getCanvas(width, height) local canvas2 = Cache.getCanvas(width, height)
@@ -507,17 +502,16 @@ function Blur:applyBackdrop(intensity, x, y, width, height, backdropCanvas)
love.graphics.setShader(self.shader) love.graphics.setShader(self.shader)
for i = 1, passes do -- Single pass with radius-controlled offset
love.graphics.setCanvas(canvas2) love.graphics.setCanvas(canvas2)
love.graphics.clear() love.graphics.clear()
self.shader:send("direction", { 1 / width, 0 }) self.shader:send("direction", { offsetMultiplier / width, 0 })
love.graphics.draw(canvas1, 0, 0) love.graphics.draw(canvas1, 0, 0)
love.graphics.setCanvas(canvas1) love.graphics.setCanvas(canvas1)
love.graphics.clear() love.graphics.clear()
self.shader:send("direction", { 0, 1 / height }) self.shader:send("direction", { 0, offsetMultiplier / height })
love.graphics.draw(canvas2, 0, 0) love.graphics.draw(canvas2, 0, 0)
end
love.graphics.setCanvas(prevCanvas) love.graphics.setCanvas(prevCanvas)
love.graphics.setShader() love.graphics.setShader()
@@ -550,21 +544,21 @@ function Blur.clearCache()
end end
--- Apply backdrop blur with caching support --- Apply backdrop blur with caching support
---@param intensity number Blur intensity (0-100) ---@param radius number Blur radius in pixels
---@param x number X position ---@param x number X position
---@param y number Y position ---@param y number Y position
---@param width number Width of region ---@param width number Width of region
---@param height number Height of region ---@param height number Height of region
---@param backdropCanvas love.Canvas Canvas containing the backdrop content ---@param backdropCanvas love.Canvas Canvas containing the backdrop content
---@param elementId string|nil Element ID for caching (nil disables caching) ---@param elementId string|nil Element ID for caching (nil disables caching)
function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas, elementId) function Blur:applyBackdropCached(radius, x, y, width, height, backdropCanvas, elementId)
-- If caching is disabled or no element ID, fall back to regular apply -- If caching is disabled or no element ID, fall back to regular apply
if not Blur._immediateModeOptimizations or not elementId then if not Blur._immediateModeOptimizations or not elementId then
return self:applyBackdrop(intensity, x, y, width, height, backdropCanvas) return self:applyBackdrop(radius, x, y, width, height, backdropCanvas)
end end
-- Generate cache key -- Generate cache key
local cacheKey = Cache.generateBlurCacheKey(elementId, x, y, width, height, intensity, self.quality, true) local cacheKey = Cache.generateBlurCacheKey(elementId, x, y, width, height, radius, self.quality, true)
-- Check cache -- Check cache
local cachedCanvas = Cache.getBlurredCanvas(cacheKey) local cachedCanvas = Cache.getBlurredCanvas(cacheKey)
@@ -593,22 +587,20 @@ function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas
return return
end end
if intensity <= 0 or width <= 0 or height <= 0 then if radius <= 0 or width <= 0 or height <= 0 then
return return
end end
-- Early exit for very low intensity (optimization) -- Early exit for very low radius (optimization)
if intensity < Cache.INTENSITY_THRESHOLD then if radius < Cache.RADIUS_THRESHOLD then
return return
end end
-- Check for large blur area in immediate mode -- Check for large blur area in immediate mode
checkLargeBlurWarning(elementId, width, height, "backdrop") checkLargeBlurWarning(elementId, width, height, "backdrop")
intensity = math.max(0, math.min(100, intensity)) -- Calculate offset multiplier based on radius and quality
local offsetMultiplier = radius / self.quality
local passes = math.ceil(intensity / 20)
passes = math.max(1, math.min(5, passes))
local canvas1 = Cache.getCanvas(width, height) local canvas1 = Cache.getCanvas(width, height)
local canvas2 = Cache.getCanvas(width, height) local canvas2 = Cache.getCanvas(width, height)
@@ -629,17 +621,16 @@ function Blur:applyBackdropCached(intensity, x, y, width, height, backdropCanvas
love.graphics.setShader(self.shader) love.graphics.setShader(self.shader)
for i = 1, passes do -- Single pass with radius-controlled offset
love.graphics.setCanvas(canvas2) love.graphics.setCanvas(canvas2)
love.graphics.clear() love.graphics.clear()
self.shader:send("direction", { 1 / width, 0 }) self.shader:send("direction", { offsetMultiplier / width, 0 })
love.graphics.draw(canvas1, 0, 0) love.graphics.draw(canvas1, 0, 0)
love.graphics.setCanvas(canvas1) love.graphics.setCanvas(canvas1)
love.graphics.clear() love.graphics.clear()
self.shader:send("direction", { 0, 1 / height }) self.shader:send("direction", { 0, offsetMultiplier / height })
love.graphics.draw(canvas2, 0, 0) love.graphics.draw(canvas2, 0, 0)
end
-- Cache the result -- Cache the result
local cachedResult = love.graphics.newCanvas(width, height) local cachedResult = love.graphics.newCanvas(width, height)

View File

@@ -70,8 +70,8 @@
---@field contentAutoSizingMultiplier {width:number?, height:number?}? -- Multiplier for auto-sized content dimensions ---@field contentAutoSizingMultiplier {width:number?, height:number?}? -- Multiplier for auto-sized content dimensions
---@field scaleCorners number? -- Scale multiplier for 9-patch corners/edges. E.g., 2 = 2x size (overrides theme setting) ---@field scaleCorners number? -- Scale multiplier for 9-patch corners/edges. E.g., 2 = 2x size (overrides theme setting)
---@field scalingAlgorithm "nearest"|"bilinear"? -- Scaling algorithm for 9-patch corners: "nearest" (sharp/pixelated) or "bilinear" (smooth) (overrides theme setting) ---@field scalingAlgorithm "nearest"|"bilinear"? -- Scaling algorithm for 9-patch corners: "nearest" (sharp/pixelated) or "bilinear" (smooth) (overrides theme setting)
---@field contentBlur {intensity:number, quality:number}? -- Blur the element's content including children (intensity: 0-100, quality: 1-10) ---@field contentBlur {radius:number, quality:number?}? -- Blur the element's content including children (radius: pixels, quality: 1-10, default: 5)
---@field backdropBlur {intensity:number, quality:number}? -- Blur content behind the element (intensity: 0-100, quality: 1-10) ---@field backdropBlur {radius:number, quality:number?}? -- Blur content behind the element (radius: pixels, quality: 1-10, default: 5)
---@field _blurInstance table? -- Internal: cached blur effect instance ---@field _blurInstance table? -- Internal: cached blur effect instance
---@field editable boolean -- Whether the element is editable (default: false) ---@field editable boolean -- Whether the element is editable (default: false)
---@field multiline boolean -- Whether the element supports multiple lines (default: false) ---@field multiline boolean -- Whether the element supports multiple lines (default: false)
@@ -2123,10 +2123,10 @@ function Element:draw(backdropCanvas)
end end
-- Apply content blur if configured -- Apply content blur if configured
if self.contentBlur and self.contentBlur.intensity > 0 and #sortedChildren > 0 then if self.contentBlur and self.contentBlur.radius > 0 and #sortedChildren > 0 then
local blurInstance = self:getBlurInstance() local blurInstance = self:getBlurInstance()
if blurInstance then if blurInstance then
Element._Blur.applyToRegion(blurInstance, self.contentBlur.intensity, self.x, self.y, borderBoxWidth, borderBoxHeight, drawChildren) Element._Blur.applyToRegion(blurInstance, self.contentBlur.radius, self.x, self.y, borderBoxWidth, borderBoxHeight, drawChildren)
else else
drawChildren() drawChildren()
end end
@@ -3190,13 +3190,13 @@ function Element:saveState()
} }
if self.backdropBlur then if self.backdropBlur then
state.blur._backdropBlurIntensity = self.backdropBlur.intensity state.blur._backdropBlurRadius = self.backdropBlur.radius
state.blur._backdropBlurQuality = self.backdropBlur.quality state.blur._backdropBlurQuality = self.backdropBlur.quality or 5
end end
if self.contentBlur then if self.contentBlur then
state.blur._contentBlurIntensity = self.contentBlur.intensity state.blur._contentBlurRadius = self.contentBlur.radius
state.blur._contentBlurQuality = self.contentBlur.quality state.blur._contentBlurQuality = self.contentBlur.quality or 5
end end
end end
@@ -3252,9 +3252,9 @@ function Element:shouldInvalidateBlurCache(oldState, newState)
or old._blurY ~= new._blurY or old._blurY ~= new._blurY
or old._blurWidth ~= new._blurWidth or old._blurWidth ~= new._blurWidth
or old._blurHeight ~= new._blurHeight or old._blurHeight ~= new._blurHeight
or old._backdropBlurIntensity ~= new._backdropBlurIntensity or old._backdropBlurRadius ~= new._backdropBlurRadius
or old._backdropBlurQuality ~= new._backdropBlurQuality or old._backdropBlurQuality ~= new._backdropBlurQuality
or old._contentBlurIntensity ~= new._contentBlurIntensity or old._contentBlurRadius ~= new._contentBlurRadius
or old._contentBlurQuality ~= new._contentBlurQuality or old._contentBlurQuality ~= new._contentBlurQuality
end end

View File

@@ -417,12 +417,12 @@ function Renderer:draw(element, backdropCanvas)
end end
-- LAYER 0.5: Draw backdrop blur if configured (before background) -- LAYER 0.5: Draw backdrop blur if configured (before background)
if self.backdropBlur and self.backdropBlur.intensity > 0 and backdropCanvas then if self.backdropBlur and self.backdropBlur.radius > 0 and backdropCanvas then
local blurInstance = self:getBlurInstance() local blurInstance = self:getBlurInstance()
if blurInstance then if blurInstance then
-- Use cached blur in immediate mode if element has an ID -- Use cached blur in immediate mode if element has an ID
local elementId = element.id and element.id ~= "" and element.id or nil local elementId = element.id and element.id ~= "" and element.id or nil
blurInstance:applyBackdropCached(self.backdropBlur.intensity, element.x, element.y, borderBoxWidth, borderBoxHeight, backdropCanvas, elementId) blurInstance:applyBackdropCached(self.backdropBlur.radius, element.x, element.y, borderBoxWidth, borderBoxHeight, backdropCanvas, elementId)
end end
end end

View File

@@ -95,8 +95,8 @@ local AnimationProps = {}
---@field contentAutoSizingMultiplier {width:number?, height:number?}? -- Multiplier for auto-sized content dimensions (default: sourced from theme or {1, 1}) ---@field contentAutoSizingMultiplier {width:number?, height:number?}? -- Multiplier for auto-sized content dimensions (default: sourced from theme or {1, 1})
---@field scaleCorners number? -- Scale multiplier for 9-patch corners/edges. E.g., 2 = 2x size (overrides theme setting) ---@field scaleCorners number? -- Scale multiplier for 9-patch corners/edges. E.g., 2 = 2x size (overrides theme setting)
---@field scalingAlgorithm "nearest"|"bilinear"? -- Scaling algorithm for 9-patch corners: "nearest" (sharp/pixelated) or "bilinear" (smooth) (overrides theme setting) ---@field scalingAlgorithm "nearest"|"bilinear"? -- Scaling algorithm for 9-patch corners: "nearest" (sharp/pixelated) or "bilinear" (smooth) (overrides theme setting)
---@field contentBlur {intensity:number, quality:number}? -- Blur the element's content including children (intensity: 0-100, quality: 1-10, default: nil) ---@field contentBlur {radius:number, quality:number?}? -- Blur the element's content including children (radius: pixels, quality: 1-10, default(quality): 5)
---@field backdropBlur {intensity:number, quality:number}? -- Blur content behind the element (intensity: 0-100, quality: 1-10, default: nil) ---@field backdropBlur {radius:number, quality:number?}? -- Blur content behind the element (radius: pixels, quality: 1-10, default(quality): 5)
---@field editable boolean? -- Whether the element is editable (default: false) ---@field editable boolean? -- Whether the element is editable (default: false)
---@field multiline boolean? -- Whether the element supports multiple lines (default: false) ---@field multiline boolean? -- Whether the element supports multiple lines (default: false)
---@field textWrap boolean|"word"|"char"? -- Text wrapping mode (default: false for single-line, "word" for multi-line) ---@field textWrap boolean|"word"|"char"? -- Text wrapping mode (default: false for single-line, "word" for multi-line)
@@ -204,7 +204,7 @@ local FlexLoveConfig = {}
---@field _blurY number ---@field _blurY number
---@field _blurWidth number ---@field _blurWidth number
---@field _blurHeight number ---@field _blurHeight number
---@field _backdropBlurIntensity number? ---@field _backdropBlurRadius number?
---@field _backdropBlurQuality string? ---@field _backdropBlurQuality number?
---@field _contentBlurIntensity number? ---@field _contentBlurRadius number?
---@field _contentBlurQuality string? ---@field _contentBlurQuality number?

View File

@@ -104,7 +104,7 @@ end
-- applyToRegion() Edge Cases -- applyToRegion() Edge Cases
-- ============================================================================ -- ============================================================================
function TestBlur:testApplyToRegionWithZeroIntensity() function TestBlur:testApplyToRegionWithZeroRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local called = false local called = false
local drawFunc = function() local drawFunc = function()
@@ -116,7 +116,7 @@ function TestBlur:testApplyToRegionWithZeroIntensity()
luaunit.assertTrue(called) luaunit.assertTrue(called)
end end
function TestBlur:testApplyToRegionWithNegativeIntensity() function TestBlur:testApplyToRegionWithNegativeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local called = false local called = false
local drawFunc = function() local drawFunc = function()
@@ -176,14 +176,14 @@ function TestBlur:testApplyToRegionWithNegativeHeight()
luaunit.assertTrue(called) luaunit.assertTrue(called)
end end
function TestBlur:testApplyToRegionWithIntensityOver100() function TestBlur:testApplyToRegionWithLargeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
end end
-- Should clamp intensity to 100 -- Should work with large radius values
blur:applyToRegion(150, 0, 0, 100, 100, drawFunc) blur:applyToRegion(150, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
end end
@@ -240,36 +240,36 @@ function TestBlur:testApplyToRegionWithVeryLargeDimensions()
luaunit.assertTrue(called) luaunit.assertTrue(called)
end end
function TestBlur:testApplyToRegionIntensityBoundaries() function TestBlur:testApplyToRegionRadiusValues()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local called = false local called = false
local drawFunc = function() local drawFunc = function()
called = true called = true
end end
-- Test boundary values that affect passes calculation -- Test various radius values
-- intensity 20 = 1 pass -- Small radius
blur:applyToRegion(5, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called)
called = false
-- Medium radius
blur:applyToRegion(10, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called)
called = false
-- Large radius
blur:applyToRegion(20, 0, 0, 100, 100, drawFunc) blur:applyToRegion(20, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
called = false called = false
-- intensity 40 = 2 passes -- Very large radius
blur:applyToRegion(40, 0, 0, 100, 100, drawFunc) blur:applyToRegion(50, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
called = false called = false
-- intensity 60 = 3 passes -- Fractional radius
blur:applyToRegion(60, 0, 0, 100, 100, drawFunc) blur:applyToRegion(2.5, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called)
called = false
-- intensity 80 = 4 passes
blur:applyToRegion(80, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called)
called = false
-- intensity 100 = 5 passes
blur:applyToRegion(100, 0, 0, 100, 100, drawFunc)
luaunit.assertTrue(called) luaunit.assertTrue(called)
end end
@@ -277,7 +277,7 @@ end
-- applyBackdrop() Edge Cases -- applyBackdrop() Edge Cases
-- ============================================================================ -- ============================================================================
function TestBlur:testApplyBackdropWithZeroIntensity() function TestBlur:testApplyBackdropWithZeroRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
@@ -290,7 +290,7 @@ function TestBlur:testApplyBackdropWithZeroIntensity()
luaunit.assertTrue(true) luaunit.assertTrue(true)
end end
function TestBlur:testApplyBackdropWithNegativeIntensity() function TestBlur:testApplyBackdropWithNegativeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
@@ -337,7 +337,7 @@ function TestBlur:testApplyBackdropWithNilCanvas()
luaunit.assertTrue(true) -- Should reach here without crash luaunit.assertTrue(true) -- Should reach here without crash
end end
function TestBlur:testApplyBackdropWithIntensityOver100() function TestBlur:testApplyBackdropWithLargeRadius()
local blur = Blur.new({quality = 5}) local blur = Blur.new({quality = 5})
local mockCanvas = { local mockCanvas = {
getDimensions = function() getDimensions = function()
@@ -345,7 +345,7 @@ function TestBlur:testApplyBackdropWithIntensityOver100()
end, end,
} }
-- Should clamp intensity to 100 -- Should work with large radius values
blur:applyBackdrop(200, 0, 0, 100, 100, mockCanvas) blur:applyBackdrop(200, 0, 0, 100, 100, mockCanvas)
luaunit.assertTrue(true) luaunit.assertTrue(true)
end end

View File

@@ -393,7 +393,7 @@ function TestCriticalFailures:test_blur_invalid_quality()
FlexLove.new({ FlexLove.new({
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = 50, quality = 0 }, contentBlur = { radius = 50, quality = 0 },
}) })
end) end)
@@ -403,7 +403,7 @@ function TestCriticalFailures:test_blur_invalid_quality()
FlexLove.new({ FlexLove.new({
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = 50, quality = -5 }, contentBlur = { radius = 50, quality = -5 },
}) })
end) end)

View File

@@ -1881,7 +1881,7 @@ end
function TestElementBlur:test_getBlurInstance_with_blur() function TestElementBlur:test_getBlurInstance_with_blur()
local element = createBasicElement({ local element = createBasicElement({
backdropBlur = { intensity = 50, quality = 5 }, backdropBlur = { radius = 50, quality = 5 },
}) })
-- Blur instance should be created when backdropBlur is set -- Blur instance should be created when backdropBlur is set
@@ -1981,7 +1981,7 @@ end
function TestElementDraw:test_draw_with_blur() function TestElementDraw:test_draw_with_blur()
local element = createBasicElement({ local element = createBasicElement({
backdropBlur = { intensity = 50, quality = 5 }, backdropBlur = { radius = 50, quality = 5 },
backgroundColor = Color.new(1, 1, 1, 0.5), backgroundColor = Color.new(1, 1, 1, 0.5),
}) })
@@ -2906,7 +2906,7 @@ function TestElementEdgeCases:test_invalid_blur_config()
id = "blur", id = "blur",
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = -10, quality = 5 }, contentBlur = { radius = -10, quality = 5 },
}) })
luaunit.assertNotNil(element) luaunit.assertNotNil(element)
@@ -2915,7 +2915,7 @@ function TestElementEdgeCases:test_invalid_blur_config()
id = "blur2", id = "blur2",
width = 100, width = 100,
height = 100, height = 100,
backdropBlur = { intensity = 150, quality = 5 }, backdropBlur = { radius = 150, quality = 5 },
}) })
luaunit.assertNotNil(element) luaunit.assertNotNil(element)
@@ -2924,7 +2924,7 @@ function TestElementEdgeCases:test_invalid_blur_config()
id = "blur3", id = "blur3",
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = 50, quality = 0 }, contentBlur = { radius = 50, quality = 0 },
}) })
luaunit.assertNotNil(element) luaunit.assertNotNil(element)
end end

View File

@@ -438,26 +438,26 @@ TestRendererBlur = {}
function TestRendererBlur:testNewWithContentBlur() function TestRendererBlur:testNewWithContentBlur()
local renderer = Renderer.new({ local renderer = Renderer.new({
contentBlur = { contentBlur = {
intensity = 5, radius = 5,
quality = "high", quality = "high",
}, },
}, createDeps()) }, createDeps())
luaunit.assertNotNil(renderer.contentBlur) luaunit.assertNotNil(renderer.contentBlur)
luaunit.assertEquals(renderer.contentBlur.intensity, 5) luaunit.assertEquals(renderer.contentBlur.radius, 5)
luaunit.assertEquals(renderer.contentBlur.quality, "high") luaunit.assertEquals(renderer.contentBlur.quality, "high")
end end
function TestRendererBlur:testNewWithBackdropBlur() function TestRendererBlur:testNewWithBackdropBlur()
local renderer = Renderer.new({ local renderer = Renderer.new({
backdropBlur = { backdropBlur = {
intensity = 10, radius = 10,
quality = "medium", quality = "medium",
}, },
}, createDeps()) }, createDeps())
luaunit.assertNotNil(renderer.backdropBlur) luaunit.assertNotNil(renderer.backdropBlur)
luaunit.assertEquals(renderer.backdropBlur.intensity, 10) luaunit.assertEquals(renderer.backdropBlur.radius, 10)
luaunit.assertEquals(renderer.backdropBlur.quality, "medium") luaunit.assertEquals(renderer.backdropBlur.quality, "medium")
end end
@@ -923,7 +923,7 @@ function TestRendererEdgeCases:test_blur_with_invalid_intensity()
id = "test1", id = "test1",
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = -10, quality = 5 }, contentBlur = { radius = -10, quality = 5 },
}) })
luaunit.assertNotNil(element1) luaunit.assertNotNil(element1)
@@ -932,7 +932,7 @@ function TestRendererEdgeCases:test_blur_with_invalid_intensity()
id = "test2", id = "test2",
width = 100, width = 100,
height = 100, height = 100,
backdropBlur = { intensity = 200, quality = 5 }, backdropBlur = { radius = 200, quality = 5 },
}) })
luaunit.assertNotNil(element2) luaunit.assertNotNil(element2)
end end
@@ -943,7 +943,7 @@ function TestRendererEdgeCases:test_blur_with_invalid_quality()
id = "test1", id = "test1",
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = 10, quality = 0 }, contentBlur = { radius = 10, quality = 0 },
}) })
luaunit.assertNotNil(element1) luaunit.assertNotNil(element1)
@@ -952,7 +952,7 @@ function TestRendererEdgeCases:test_blur_with_invalid_quality()
id = "test2", id = "test2",
width = 100, width = 100,
height = 100, height = 100,
contentBlur = { intensity = 10, quality = 100 }, contentBlur = { radius = 10, quality = 100 },
}) })
luaunit.assertNotNil(element2) luaunit.assertNotNil(element2)
end end