From d74198b7db89a6d40bcfd9172c677a14b978d547 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 29 Sep 2010 18:54:20 +0200 Subject: [PATCH] gears.color: Add much more sophiscated stuff Signed-off-by: Uli Schlachter --- lib/gears/color.lua.in | 129 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/lib/gears/color.lua.in b/lib/gears/color.lua.in index 8e4ff9c47..2cc5ceeb8 100644 --- a/lib/gears/color.lua.in +++ b/lib/gears/color.lua.in @@ -9,15 +9,27 @@ local string = string local table = table local tonumber = tonumber local unpack = unpack +local pairs = pairs +local type = type +local capi = { + oocairo = oocairo +} module("gears.color") +--- Parse a HTML-color. +-- This function can parse colors like #rrggbb and #rrggbbaa. +-- For example, parse_color("#00ff00ff") would return 0, 1, 0, 1. -- Thanks to #lua for this. :) - +-- @param col The color to parse +-- @return 4 values which each are in the range [0, 1]. function parse_color(col) local rgb = {} for pair in string.gmatch(col, "[^#].") do - table.insert(rgb, tonumber(pair, 16) / 255) + local i = tonumber(pair, 16) + if i then + table.insert(rgb, i / 255) + end end while #rgb < 4 do table.insert(rgb, 1) @@ -25,6 +37,117 @@ function parse_color(col) return unpack(rgb) end -setmetatable(_M, { __call = function (_, ...) return parse_color(...) end }) +--- Find all numbers in a string +-- @param s The string to parse +-- @return Each number found as a separate value +local function parse_numbers(s) + local res = {} + for k in string.gmatch(s, "-?[0-9]+[.]?[0-9]*") do + table.insert(res, tonumber(k)) + end + return unpack(res) +end + +--- Create a solid pattern +-- @param col The color for the pattern +-- @return A cairo pattern object +function create_solid_pattern(col) + local col = col + if col == nil then + col = "#000000" + end + return capi.oocairo.pattern_create_rgba(parse_color(col)) +end + +--- Create an image pattern from a png file +-- @param file The filename of the file +-- @return a cairo pattern object +function create_png_pattern(file) + local image = capi.oocairo.image_surface_create_from_png(file) + return capi.oocairo.pattern_create_for_surface(image) +end + +--- Add stops to the given pattern. +-- @param p The cairo pattern to add stops to +-- @param iterator An iterator that returns strings. Each of those strings +-- should be in the form place,color where place is in [0, 1]. +function add_stops(p, iterator) + for k in iterator do + local sub = string.gmatch(k, "[^,]+") + local point, color = sub(), sub() + p:add_color_stop_rgba(point, parse_color(color)) + end +end + +--- Create a linear pattern object. +-- The pattern is created from a string. This string should have the following +-- form: "x0,y0:x1,y1:" +-- x0,y0 and x1,y1 are the start and stop point of the pattern. +-- For the explanation of "", see add_stops(). +-- @param arg The argument describing the pattern +-- @return a cairo pattern object +-- @nname create_linear_pattern +-- @nclass function + +--- Create a radial pattern object. +-- The pattern is created from a string. This string should have the following +-- form: "x0,y0,r0:x1,y1,r1:" +-- x0,y0 and x1,y1 are the start and stop point of the pattern. +-- r0 and r1 are the radii of the start / stop circle. +-- For the explanation of "", see add_stops(). +-- @param arg The argument describing the pattern +-- @return a cairo pattern object +-- @nname create_radial_pattern +-- @nclass function + +for k, v in pairs({ linear = capi.oocairo.pattern_create_linear, + radial = capi.oocairo.pattern_create_radial}) do + _M["create_" .. k .. "_pattern"] = function(arg) + local iterator = string.gmatch(arg, "[^:]+") + -- Create a table where each entry is a number from the original string + local args = { parse_numbers(iterator()) } + local to = { parse_numbers(iterator()) } + -- Now merge those two tables + for k, v in pairs(to) do + table.insert(args, v) + end + -- And call our creator function with the values + local p = v(unpack(args)) + + add_stops(p, iterator) + return p + end +end + +types = { + solid = create_solid_pattern, + png = create_png_pattern, + linear = create_linear_pattern, + radial = create_radial_pattern +} + +--- Create a pattern from a given string. +-- This function can create solid, linear, radial and png patterns. In general, +-- patterns are specified as "type:arguments". "arguments" is specific to the +-- pattern used. For example, one can use +-- "linear:50,50,10:55,55,30:0,#ff0000:0.5,#00ff00:1,#0000ff" +-- Any argument that cannot be understood is passed to create_solid_pattern(). +-- @see create_solid_pattern, create_png_pattern, create_linear_pattern, +-- create_radial_pattern +-- @param col The string describing the pattern. +-- @return a cairo pattern object +function create_pattern(col) + if type(col) == "string" then + local t = string.match(col, "[^:]+") + if types[t] then + local pos = string.len(t) + local arg = string.sub(col, pos + 2) + return types[t](arg) + end + end + return create_solid_pattern(col) +end + +setmetatable(_M, { __call = function (_, ...) return create_pattern(...) end }) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80