From 0956aa01d9e664a1eed3088312ee130b07f103c6 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 9 Jan 2016 18:17:30 +0100 Subject: [PATCH] Add support for short/long colors This adds support to gears.color.parse_color to parse things like "#fff" (one character per color component, without alpha) and "#ffff0000ffff0000" (four characters per component, with alpha). This makes sense on its own, but should also help with https://github.com/awesomeWM/awesome/issues/585. Signed-off-by: Uli Schlachter --- lib/gears/color.lua | 25 ++++++++++++++++---- spec/gears/color_spec.lua | 50 +++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/lib/gears/color.lua b/lib/gears/color.lua index 132d1d3e0..db347c662 100644 --- a/lib/gears/color.lua +++ b/lib/gears/color.lua @@ -28,13 +28,28 @@ local pattern_cache -- @usage -- This will return 0, 1, 0, 1 -- gears.color.parse_color("#00ff00ff") function color.parse_color(col) + -- Get all hex chars local rgb = {} - for pair in string.gmatch(col, "[^#].") do - local i = tonumber(pair, 16) - if i then - table.insert(rgb, i / 255) - end + for char in string.gmatch(col, "[^#]") do + table.insert(rgb, tonumber(char, 16) / 0xf) end + -- Merge consecutive values until we have at most four groups (rgba) + local factor = 0xf + while #rgb > 4 do + local merged = {} + local key, value = next(rgb, nil) + local next_factor = (factor + 1)*(factor + 1) - 1 + while key do + local key2, value2 = next(rgb, key) + local v1, v2 = value * factor, value2 * factor + local new = v1 * (factor + 1) + v2 + table.insert(merged, new / next_factor) + key, value = next(rgb, key2) + end + rgb = merged + factor = next_factor + end + -- Add missing groups (missing alpha) while #rgb < 4 do table.insert(rgb, 1) end diff --git a/spec/gears/color_spec.lua b/spec/gears/color_spec.lua index 66fcfdce6..2098e6307 100644 --- a/spec/gears/color_spec.lua +++ b/spec/gears/color_spec.lua @@ -11,26 +11,62 @@ describe("gears.color", function() describe("parse_color", function() local function test(e_r, e_g, e_b, e_a, input) local o_r, o_g, o_b, o_a, unused = color.parse_color(input) - assert.is.same(o_r, e_r / 255) - assert.is.same(o_g, e_g / 255) - assert.is.same(o_b, e_b / 255) + assert.is.same(o_r, e_r / 0xff) + assert.is.same(o_g, e_g / 0xff) + assert.is.same(o_b, e_b / 0xff) + assert.is.same(o_a, e_a / 0xff) assert.is_nil(unused) end it("black", function() - test(0, 0, 0, 255, "#000000") + test(0, 0, 0, 0xff, "#000000") end) it("opaque black", function() - test(0, 0, 0, 255, "#000000ff") + test(0, 0, 0, 0xff, "#000000ff") end) it("transparent gray", function() - test(128, 128, 128, 128, "#80808080") + test(0x80, 0x80, 0x80, 0x80, "#80808080") end) it("transparent white", function() - test(255, 255, 255, 127, "#ffffff7f") + test(0xff, 0xff, 0xff, 0x7f, "#ffffff7f") + end) + + describe("different lengths", function() + local function gray(e, e_a, input) + local o_r, o_g, o_b, o_a, unused = color.parse_color(input) + assert.is.same(o_r, e) + assert.is.same(o_g, e) + assert.is.same(o_b, e) + assert.is.same(o_a, e_a) + assert.is_nil(unused) + end + + it("rgb", function() + gray(0x8/0xf, 1, "#888") + end) + + it("rgba", function() + gray(0x8/0xf, 0x8/0xf, "#8888") + end) + + it("rrggbb", function() + gray(0x80/0xff, 1, "#808080") + end) + + it("rrggbbaa", function() + gray(0x80/0xff, 0x80/0xff, "#80808080") + end) + + it("rrrrggggbbbb", function() + gray(0x8000/0xffff, 1, "#800080008000") + end) + + it("rrrrggggbbbbaaaa", function() + gray(0x8000/0xffff, 0x8000/0xffff, "#8000800080008000") + end) end) end)