Merge pull request #3087 from ndgnuh/shape.squircle

Shape.squircle
This commit is contained in:
mergify[bot] 2020-05-04 08:41:17 +00:00 committed by GitHub
commit 6f1702541c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 163 additions and 0 deletions

View File

@ -76,5 +76,19 @@ function gmath.round(x)
return math.floor(x + 0.5) return math.floor(x + 0.5)
end end
--- Return the sign of the number x
-- return 1 if x is positive, -1 if negative and 0 if x is 0
-- @tparam number x
-- @treturn integer
-- @staticfct gears.math.sign
function gmath.sign(x)
if x > 0 then
return 1
elseif x < 0 then
return -1
else
return 0
end
end
return gmath return gmath

View File

@ -41,14 +41,137 @@
-- @themelib gears.shape -- @themelib gears.shape
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
local g_matrix = require( "gears.matrix" ) local g_matrix = require( "gears.matrix" )
local g_math = require( "gears.math" )
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
local atan2 = math.atan2 or math.atan -- lua 5.3 compat local atan2 = math.atan2 or math.atan -- lua 5.3 compat
local min = math.min local min = math.min
local max = math.max
local cos = math.cos local cos = math.cos
local sin = math.sin local sin = math.sin
local abs = math.abs
local pow = math.pow -- luacheck: globals math.pow
if not pow then
-- math.pow can be disabled in Lua 5.3 via LUA_COMPAT_MATHLIB
pow = function(x, y)
return x^y
end
end
local module = {} local module = {}
--- Add a squircle shape with only some of the corner are "circled" to the current path.
-- The squircle is not exactly as the definition.
-- It will expand to the shape's width and height, kinda like an ellipse
--
-- @DOC_gears_shape_partial_squircle_EXAMPLE@
--
-- @param cr A cairo context
-- @tparam number width The shape width
-- @tparam number height The shape height
-- @tparam boolean tl If the top left corner is rounded
-- @tparam boolean tr If the top right corner is rounded
-- @tparam boolean br If the bottom right corner is rounded
-- @tparam boolean bl If the bottom left corner is rounded
-- @tparam number rate The "squareness" of the squircle, should be greater than 1
-- @tparam number delta The "smoothness" of the shape, delta must be greater than 0.01 and will be reset to 0.01 if not
-- @staticfct gears.shape.partial_squircle
function module.partial_squircle(cr, width, height, tl, tr, br, bl, rate, delta)
-- rate ~ 2 can be used by icon
-- this shape doesn't really fit clients
-- but you can still use with rate ~ 32
rate = rate or 2
-- smaller the delta the smoother the shape
-- but probably more laggy
-- so we'll limit delta to the miminum of 0.01
-- so people don't burn their computer
delta = delta or 1 / max(width, height)
delta = delta > 0.01 and delta or 0.01
-- just ellipse things
local a = width / 2
local b = height / 2
local phi = 0
-- move to origin
-- the shape goes counter clock wise
-- start from (w h / 2)
cr:save()
cr:translate(a, b)
cr:move_to(a, 0)
-- draw the corner if that corner is rounded
local curved_corner = function()
local end_angle = phi + math.pi / 2
while phi < end_angle do
local cosphi = cos(phi)
local sinphi = sin(phi)
local x = a * pow(abs(cosphi), 1 / rate) * g_math.sign(cosphi)
local y = b * pow(abs(sinphi), 1 / rate) * g_math.sign(sinphi)
-- so weird, y axis is inverted
cr:line_to(x, -y)
phi = phi + delta
end
end
-- draw with polar cord
-- draw top right
if tr then
curved_corner()
else
cr:move_to(a, 0)
cr:line_to(a, -b)
cr:line_to(0, -b)
phi = math.pi * 0.5
end
-- draw top left
if tl then
curved_corner()
else
cr:line_to(-a, -b)
cr:line_to(-a, 0)
phi = math.pi
end
if bl then
curved_corner()
else
cr:line_to(-a, b)
cr:line_to( 0, b)
phi = math.pi * 1.5
end
-- bottom right
if br then
curved_corner()
else
cr:line_to(a, b)
cr:line_to(a, 0)
phi = math.pi * 2
end
-- it's time to stop
cr:close_path()
-- restore cairo context
cr:restore()
end
--- Add a squircle shape to the current path.
-- This will behave the same as `partial_squircle`
--
-- @DOC_gears_shape_squircle_EXAMPLE@
--
-- @param cr A cairo context
-- @tparam number width The shape width
-- @tparam number height The shape height
-- @tparam number rate The "squareness" of the squircle, should be greater than 1
-- @tparam number delta The "smoothness" of the shape, delta must be greater than 0.01 and will be reset to 0.01 if not
-- @staticfct gears.shape.squircle
function module.squircle(cr, width, height, rate, delta)
module.partial_squircle(cr, width, height, true, true, true, true, rate, delta)
end
--- Add a star shape to the current path. --- Add a star shape to the current path.
-- The star size will be the minimum of the given width and weight -- The star size will be the minimum of the given width and weight
-- --

View File

@ -0,0 +1,13 @@
--DOC_GEN_IMAGE --DOC_HIDE
local shape,cr,show = ... --DOC_HIDE
shape.partial_squircle(cr, 70, 70, false, true)
show(cr) --DOC_HIDE
shape.partial_squircle(cr, 70, 70, true, false, true)
show(cr) --DOC_HIDE
shape.partial_squircle(cr, 70, 70, true, false, true, true)
show(cr) --DOC_HIDE
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -0,0 +1,13 @@
--DOC_GEN_IMAGE --DOC_HIDE
local shape,cr,show = ... --DOC_HIDE
shape.squircle(cr, 70, 70, 2)
show(cr) --DOC_HIDE
shape.squircle(cr, 70, 70, 8)
show(cr) --DOC_HIDE
shape.squircle(cr, 70, 70, 1.5)
show(cr) --DOC_HIDE
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80