Merge pull request #655 from Elv13/upstream_shape_api_p3
Add various methods to improve the new shape API
This commit is contained in:
commit
502c3631d2
|
@ -52,6 +52,22 @@ function matrix.create_rotate(angle)
|
|||
return matrix.create(c, s, -s, c, 0, 0)
|
||||
end
|
||||
|
||||
--- Create a matrix copy
|
||||
-- @return A new matrix identical to `other`
|
||||
function matrix:copy()
|
||||
local m = matrix.create(
|
||||
self.xx, self.yx, self.xy,
|
||||
self.yy, self.x0, self.y0
|
||||
)
|
||||
|
||||
-- Used internally
|
||||
if rawget(self, "_call") then
|
||||
rawset(m, "_call", self._call)
|
||||
end
|
||||
|
||||
return m
|
||||
end
|
||||
|
||||
--- Translate this matrix
|
||||
-- @tparam number x The translation in x direction.
|
||||
-- @tparam number y The translation in y direction.
|
||||
|
@ -75,6 +91,17 @@ function matrix:rotate(angle)
|
|||
return matrix.create_rotate(angle):multiply(self)
|
||||
end
|
||||
|
||||
--- Rotate a shape from a custom point
|
||||
-- @tparam number x The horizontal rotation point
|
||||
-- @tparam number y The vertical rotation point
|
||||
-- @tparam number angle The angle (in radiant: -2*math.pi to 2*math.pi)
|
||||
-- @return A transformation object
|
||||
function matrix:rotate_at(x, y, angle)
|
||||
return self * matrix.create_translate( -x, -y )
|
||||
* matrix.create_rotate ( angle )
|
||||
* matrix.create_translate( x, y )
|
||||
end
|
||||
|
||||
--- Invert this matrix
|
||||
-- @return A new matrix describing the inverse transformation.
|
||||
function matrix:invert()
|
||||
|
@ -94,12 +121,19 @@ end
|
|||
-- @tparam gears.matrix|cairo.Matrix other The other matrix to multiply with.
|
||||
-- @return The multiplication result.
|
||||
function matrix:multiply(other)
|
||||
return matrix.create(self.xx * other.xx + self.yx * other.xy,
|
||||
self.xx * other.yx + self.yx * other.yy,
|
||||
self.xy * other.xx + self.yy * other.xy,
|
||||
self.xy * other.yx + self.yy * other.yy,
|
||||
self.x0 * other.xx + self.y0 * other.xy + other.x0,
|
||||
self.x0 * other.yx + self.y0 * other.yy + other.y0)
|
||||
local ret = matrix.create(self.xx * other.xx + self.yx * other.xy,
|
||||
self.xx * other.yx + self.yx * other.yy,
|
||||
self.xy * other.xx + self.yy * other.xy,
|
||||
self.xy * other.yx + self.yy * other.yy,
|
||||
self.x0 * other.xx + self.y0 * other.xy + other.x0,
|
||||
self.x0 * other.yx + self.y0 * other.yy + other.y0)
|
||||
|
||||
-- Used internally
|
||||
if rawget(self, "_call") or rawget(other, "_call") then
|
||||
rawset(ret, "_call", self._call or other._call)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Check if two matrices are equal.
|
||||
|
@ -189,6 +223,7 @@ matrix_mt.__newindex = error
|
|||
matrix_mt.__eq = matrix.equals
|
||||
matrix_mt.__mul = matrix.multiply
|
||||
matrix_mt.__tostring = matrix.tostring
|
||||
matrix_mt.__call = function(self, ...) return self._call(self, ...) end
|
||||
|
||||
--- A constant for the identity matrix.
|
||||
matrix.identity = matrix.create(1, 0, 0, 1, 0, 0)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
-- @release @AWESOME_VERSION@
|
||||
-- @module gears.shape
|
||||
---------------------------------------------------------------------------
|
||||
local g_matrix = require( "gears.matrix" )
|
||||
|
||||
local module = {}
|
||||
|
||||
|
@ -55,4 +56,142 @@ function module.rounded_bar(cr, width, height)
|
|||
module.rounded_rect(cr, width, height, height / 2)
|
||||
end
|
||||
|
||||
--- A rounded rectangle with a triangle at the top
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape with
|
||||
-- @tparam number height The shape height
|
||||
-- @tparam[opt=5] number corner_radius The corner radius
|
||||
-- @tparam[opt=10] number arrow_size The width and height of the arrow
|
||||
-- @tparam[opt=width/2 - arrow_size/2] number arrow_position The position of the arrow
|
||||
function module.infobubble(cr, width, height, corner_radius, arrow_size, arrow_position)
|
||||
local corner_radius = corner_radius or 5
|
||||
local arrow_size = arrow_size or 10
|
||||
local arrow_position = arrow_position or width/2 - arrow_size/2
|
||||
|
||||
cr:move_to(0 ,corner_radius)
|
||||
|
||||
-- Top left corner
|
||||
cr:arc(corner_radius, corner_radius+arrow_size, (corner_radius), math.pi, 3*(math.pi/2))
|
||||
|
||||
-- The arrow triangle (still at the top)
|
||||
cr:line_to(arrow_position , arrow_size )
|
||||
cr:line_to(arrow_position + arrow_size , 0 )
|
||||
cr:line_to(arrow_position + 2*arrow_size , arrow_size )
|
||||
|
||||
-- Complete the rounded rounded rectangle
|
||||
cr:arc(width-corner_radius, corner_radius+arrow_size , (corner_radius) , 3*(math.pi/2) , math.pi*2 )
|
||||
cr:arc(width-corner_radius, height-(corner_radius) , (corner_radius) , math.pi*2 , math.pi/2 )
|
||||
cr:arc(corner_radius , height-(corner_radius) , (corner_radius) , math.pi/2 , math.pi )
|
||||
|
||||
-- Close path
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
--- A rectangle terminated by an arrow
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape with
|
||||
-- @tparam number height The shape height
|
||||
function module.rectangular_tag(cr, width, height)
|
||||
cr:move_to(0 , height/2)
|
||||
cr:line_to(height/2 , 0 )
|
||||
cr:line_to(width , 0 )
|
||||
cr:line_to(width , height )
|
||||
cr:line_to(height/2 , height )
|
||||
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
--- A simple arrow shape
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape with
|
||||
-- @tparam number height The shape height
|
||||
-- @tparam[opt=head_width] number head_width The width of the head (/\) of the arrow
|
||||
-- @tparam[opt=width /2] number shaft_width The width of the shaft of the arrow
|
||||
-- @tparam[opt=height/2] number shaft_length The head_length of the shaft (the rest is the head)
|
||||
function module.arrow(cr, width, height, head_width, shaft_width, shaft_length)
|
||||
local shaft_length = shaft_length or height / 2
|
||||
local shaft_width = shaft_width or width / 2
|
||||
local head_width = head_width or width
|
||||
local head_length = height - shaft_length
|
||||
|
||||
cr:move_to ( width/2 , 0 )
|
||||
cr:rel_line_to( head_width/2 , head_length )
|
||||
cr:rel_line_to( -(head_width-shaft_width)/2 , 0 )
|
||||
cr:rel_line_to( 0 , shaft_length )
|
||||
cr:rel_line_to( -shaft_width , 0 )
|
||||
cr:rel_line_to( 0 , -shaft_length )
|
||||
cr:rel_line_to( -(head_width-shaft_width)/2 , 0 )
|
||||
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
--- A squeezed hexagon filling the rectangle
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape with
|
||||
-- @tparam number height The shape height
|
||||
function module.hexagon(cr, width, height)
|
||||
cr:move_to(height/2,0)
|
||||
cr:line_to(width-height/2,0)
|
||||
cr:line_to(width,height/2)
|
||||
cr:line_to(width-height/2,height)
|
||||
cr:line_to(height/2,height)
|
||||
cr:line_to(0,height/2)
|
||||
cr:line_to(height/2,0)
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
--- Double arrow popularized by the vim-powerline module
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape with
|
||||
-- @tparam number height The shape height
|
||||
-- @tparam[opt=height/2] number arrow_depth The width of the arrow part of the shape
|
||||
function module.powerline(cr, width, height, arrow_depth)
|
||||
local arrow_depth = arrow_depth or height/2
|
||||
cr:move_to(0 , 0 )
|
||||
cr:line_to(width - arrow_depth , 0 )
|
||||
cr:line_to(width , height/2 )
|
||||
cr:line_to(width - arrow_depth , height )
|
||||
cr:line_to(0 , height )
|
||||
cr:line_to(arrow_depth , height/2 )
|
||||
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
--- An isosceles triangle
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape with
|
||||
-- @tparam number height The shape height
|
||||
function module.isosceles_triangle(cr, width, height)
|
||||
cr:move_to( width/2, 0 )
|
||||
cr:line_to( width , height )
|
||||
cr:line_to( 0 , height )
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
--- Ajust the shape using a transformation object
|
||||
--
|
||||
-- Apply various transformations to the shape
|
||||
--
|
||||
-- @usage gears.shape.transform(gears.shape.rounded_bar)
|
||||
-- : rotate(math.pi/2)
|
||||
-- : translate(10, 10)
|
||||
--
|
||||
-- @param shape A shape function
|
||||
-- @return A transformation handle, also act as a shape function
|
||||
function module.transform(shape)
|
||||
|
||||
-- Apply the transformation matrix and apply the shape, then restore
|
||||
local function apply(self, cr, width, height, ...)
|
||||
cr:save()
|
||||
cr:transform(self:to_cairo_matrix())
|
||||
shape(cr, width, height, ...)
|
||||
cr:restore()
|
||||
end
|
||||
|
||||
local matrix = g_matrix.identity:copy()
|
||||
rawset(matrix, "_call", apply)
|
||||
|
||||
return matrix
|
||||
end
|
||||
|
||||
return module
|
||||
|
|
|
@ -9,6 +9,7 @@ local setmetatable = setmetatable
|
|||
local type = type
|
||||
local capi = { awesome = awesome }
|
||||
local cairo = require("lgi").cairo
|
||||
local color = nil
|
||||
local gdebug = require("gears.debug")
|
||||
|
||||
-- Keep this in sync with build-utils/lgi-check.sh!
|
||||
|
@ -152,6 +153,32 @@ function surface.duplicate_surface(s)
|
|||
return result
|
||||
end
|
||||
|
||||
--- Create a surface from a `gears.shape`
|
||||
-- Any additional parameters will be passed to the shape function
|
||||
-- @tparam number width The surface width
|
||||
-- @tparam number height The surface height
|
||||
-- @param shape A `gears.shape` compatible function
|
||||
-- @param[opt=white] shape_color The shape color or pattern
|
||||
-- @param[opt=transparent] bg_color The surface background color
|
||||
-- @treturn cairo.surface the new surface
|
||||
function surface.load_from_shape(width, height, shape, shape_color, bg_color, ...)
|
||||
color = color or require("gears.color")
|
||||
|
||||
local img = cairo.ImageSurface(cairo.Format.ARGB32, width, height)
|
||||
local cr = cairo.Context(img)
|
||||
|
||||
cr:set_source(color(bg_color or "#00000000"))
|
||||
cr:paint()
|
||||
|
||||
cr:set_source(color(shape_color or "#000000"))
|
||||
|
||||
shape(cr, width, height, ...)
|
||||
|
||||
cr:fill()
|
||||
|
||||
return img
|
||||
end
|
||||
|
||||
--- Apply a shape to a client or a wibox.
|
||||
--
|
||||
-- If the wibox or client size change, this function need to be called
|
||||
|
|
|
@ -12,6 +12,7 @@ local pairs = pairs
|
|||
local type = type
|
||||
local pcall = pcall
|
||||
local print = print
|
||||
local unpack = unpack or table.unpack
|
||||
|
||||
local imagebox = { mt = {} }
|
||||
|
||||
|
@ -30,6 +31,12 @@ function imagebox:draw(context, cr, width, height)
|
|||
|
||||
cr:scale(aspect, aspect)
|
||||
end
|
||||
|
||||
-- Set the clip
|
||||
if self._clip_shape then
|
||||
cr:clip(self._clip_shape(cr, width, height, unpack(self._clip_args)))
|
||||
end
|
||||
|
||||
cr:set_source_surface(self._image, 0, 0)
|
||||
cr:paint()
|
||||
end
|
||||
|
@ -107,6 +114,19 @@ function imagebox:set_image(image)
|
|||
return true
|
||||
end
|
||||
|
||||
--- Set a clip shape for this imagebox
|
||||
-- A clip shape define an area where the content is displayed and one where it
|
||||
-- is trimmed.
|
||||
--
|
||||
-- Any other parameters will be passed to the clip shape function
|
||||
--
|
||||
-- @param clip_shape A `gears_shape` compatible shape function
|
||||
function imagebox:set_clip_shape(clip_shape, ...)
|
||||
self._clip_shape = clip_shape
|
||||
self._clip_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Should the image be resized to fit into the available space?
|
||||
-- @param allowed If false, the image will be clipped, else it will be resized
|
||||
-- to fit into the available space.
|
||||
|
@ -117,10 +137,12 @@ function imagebox:set_resize(allowed)
|
|||
end
|
||||
|
||||
--- Returns a new imagebox
|
||||
-- Any other arguments will be passed to the clip shape function
|
||||
-- @param image the image to display, may be nil
|
||||
-- @param resize_allowed If false, the image will be clipped, else it will be resized
|
||||
-- to fit into the available space.
|
||||
local function new(image, resize_allowed)
|
||||
-- @param clip_shape A `gears.shape` compatible function
|
||||
local function new(image, resize_allowed, clip_shape)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(imagebox) do
|
||||
|
@ -136,6 +158,9 @@ local function new(image, resize_allowed)
|
|||
ret:set_resize(resize_allowed)
|
||||
end
|
||||
|
||||
ret._clip_shape = clip_shape
|
||||
ret._clip_args = {}
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue