checkpoint colors

This commit is contained in:
jtm
2012-03-11 14:47:58 +00:00
parent f7cdd98643
commit 1fab881863
6 changed files with 430 additions and 25 deletions

View File

@@ -100,17 +100,26 @@ class Color():
def hue(self, *args): def hue(self, *args):
""" """
""" """
pass if args:
h, l, s = self._hextohls(args[0])
return round(h * 360, 3)
raise ValueError('Illegal color values')
def saturation(self, *args): def saturation(self, *args):
""" """
""" """
pass if args:
h, l, s = self._hextohls(args[0])
return s * 100
raise ValueError('Illegal color values')
def lightness(self, *args): def lightness(self, *args):
""" """
""" """
pass if args:
h, l, s = self._hextohls(args[0])
return l * 100
raise ValueError('Illegal color values')
def opacity(self, *args): def opacity(self, *args):
""" """
@@ -156,6 +165,7 @@ class Color():
def grayscale(self, *args): def grayscale(self, *args):
""" """
Simply 100% desaturate.
""" """
if len(args) == 2: if len(args) == 2:
return self.desaturate(args[0], 100) return self.desaturate(args[0], 100)
@@ -163,6 +173,7 @@ class Color():
def greyscale(self, *args): def greyscale(self, *args):
""" """
Wrapper for grayscale
""" """
return self.grayscale(*args) return self.grayscale(*args)
@@ -182,22 +193,43 @@ class Color():
def mix(self, *args): def mix(self, *args):
""" """
Mix to colors This algorithm factors in both the user-provided weight
and the difference between the alpha values of the two colors
to decide how to perform the weighted average of the two RGB values.
It works by first normalizing both parameters to be within [-1, 1],
where 1 indicates "only use color1", -1 indicates "only use color 0",
and all values in between indicated a proportionately weighted average.
Once we have the normalized variables w and a,
we apply the formula (w + a)/(1 + w*a)
to get the combined weight (in [-1, 1]) of color1.
This formula has two especially nice properties:
* When either w or a are -1 or 1, the combined weight is also that number
(cases where w * a == -1 are undefined, and handled as a special case).
* When a is 0, the combined weight is w, and vice versa
Finally, the weight of color1 is renormalized to be within [0, 1]
and the weight of color2 is given by 1 minus the weight of color1.
Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
http://sass-lang.com http://sass-lang.com
""" """
if len(args) >= 2: if len(args) >= 2:
try: try:
c1, c2, w = args c1, c2, w = args
if type(w) == str: w = int(w.strip('%'))
w = ((w / 100.0) * 2) - 1
except ValueError: except ValueError:
c1, c2 = args c1, c2 = args
w = 1 w = 50
if type(w) == str: w = int(w.strip('%'))
w = ((w / 100.0) * 2) - 1
rgb1 = self._hextorgb(c1) rgb1 = self._hextorgb(c1)
rgb2 = self._hextorgb(c2) rgb2 = self._hextorgb(c2)
a = 0 a = 0
w1 = (((w if (w * a) == -1 else (w + a)) / (1 + w * a)) + 1) / 2.0 w1 = (((w if w * a == -1 else w + a) / (1 + w * a)) + 1)
w1 = w1 / 2.0
w2 = 1 - w1 w2 = 1 - w1
rgb = [ rgb = [
rgb1[0] * w1 + rgb2[0] * w2, rgb1[0] * w1 + rgb2[0] * w2,

154
lesscpy/test/css/colors.css Normal file
View File

@@ -0,0 +1,154 @@
#yellow #short {
color: #ffeeaa;
}
#yellow #long {
color: #ffeeaa;
}
#blue #short {
color: #0000ff;
}
#blue #long {
color: #0000ff;
}
#overflow .a {
color: #000000;
}
#overflow .b {
color: #ffffff;
}
#overflow .c {
color: #ffffff;
}
#overflow .d {
color: #00ff00;
}
#grey {
color: #c8c8c8;
}
#808080 {
color: #808080;
}
#00ff00 {
color: #00ff00;
}
.hsl {
color: #ffffff;
color: #ffffff;
color: #000000;
color: #000000;
}
.saturate {
color: #565454;
color: #5e4c4c;
color: #664444;
color: #773333;
color: #882222;
color: #aa0000;
color: #000000;
color: #000000;
color: #ffffff;
color: #ffffff;
color: #29332f;
color: #243830;
color: #203c31;
color: #174533;
color: #0d4f35;
color: #005c37;
}
.desaturate {
color: #555555;
color: #555555;
color: #555555;
color: #555555;
color: #555555;
color: #555555;
color: #000000;
color: #000000;
color: #ffffff;
color: #ffffff;
color: #29332f;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
}
.lighten {
color: #585858;
color: #6e6e6e;
color: #888888;
color: #bbbbbb;
color: #eeeeee;
color: #ffffff;
color: #ffffff;
color: #000000;
color: #ffffff;
color: #ffffff;
color: #2b3632;
color: #404f49;
color: #566c63;
color: #88a096;
color: #c1cdc8;
color: #ffffff;
}
.lighten {
color: #525252;
color: #3b3b3b;
color: #222222;
color: #000000;
color: #000000;
color: #000000;
color: #000000;
color: #000000;
color: #000000;
color: #ffffff;
color: #27302c;
color: #121715;
color: #000000;
color: #000000;
color: #000000;
color: #000000;
}
.spin {
color: #555555;
color: #555555;
color: #555555;
color: #555555;
color: #555555;
color: #555555;
color: #000000;
color: #000000;
color: #ffffff;
color: #ffffff;
color: #29332f;
color: #29332d;
color: #293332;
color: #2a3329;
color: #292d33;
color: #2c2933;
}
.grayscale {
color: #000000;
color: #000000;
color: #ffffff;
color: #ffffff;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
color: #2e2e2e;
}
.mix {
color: #7f007f;
color: #7f7f7f;
color: #7f9055;
color: #3f00bf;
color: #ff0000;
color: #0000ff;
}
.vars {
color: #f6430f;
background-color: #f8b38d;
color: #f1dfda;
}

20
lesscpy/test/css/colors.min.css vendored Normal file
View File

@@ -0,0 +1,20 @@
#yellow #short{color:#ffeeaa;}
#yellow #long{color:#ffeeaa;}
#blue #short{color:#0000ff;}
#blue #long{color:#0000ff;}
#overflow .a{color:#000000;}
#overflow .b{color:#ffffff;}
#overflow .c{color:#ffffff;}
#overflow .d{color:#00ff00;}
#grey{color:#c8c8c8;}
#808080{color:#808080;}
#00ff00{color:#00ff00;}
.hsl{color:#ffffff;color:#ffffff;color:#000000;color:#000000;}
.saturate{color:#565454;color:#5e4c4c;color:#664444;color:#773333;color:#882222;color:#aa0000;color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#29332f;color:#243830;color:#203c31;color:#174533;color:#0d4f35;color:#005c37;}
.desaturate{color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#29332f;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;}
.lighten{color:#585858;color:#6e6e6e;color:#888888;color:#bbbbbb;color:#eeeeee;color:#ffffff;color:#ffffff;color:#000000;color:#ffffff;color:#ffffff;color:#2b3632;color:#404f49;color:#566c63;color:#88a096;color:#c1cdc8;color:#ffffff;}
.lighten{color:#525252;color:#3b3b3b;color:#222222;color:#000000;color:#000000;color:#000000;color:#000000;color:#000000;color:#000000;color:#ffffff;color:#27302c;color:#121715;color:#000000;color:#000000;color:#000000;color:#000000;}
.spin{color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#555555;color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#29332f;color:#29332d;color:#293332;color:#2a3329;color:#292d33;color:#2c2933;}
.grayscale{color:#000000;color:#000000;color:#ffffff;color:#ffffff;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;color:#2e2e2e;}
.mix{color:#7f007f;color:#7f7f7f;color:#7f9055;color:#3f00bf;color:#ff0000;color:#0000ff;}
.vars{color:#f6430f;background-color:#f8b38d;color:#f1dfda;}

View File

@@ -0,0 +1,20 @@
/*
Color alpha-channel
*/
#hsla_rgba {
color: hsla(31, 1%, 4%, 60%);
color: hsla(31, 10%, 4%, 60%);
color: hsla(31, 30%, 4%, 60%);
color: hsla(31, 60%, 4%, 60%);
color: hsla(31, 100%, 4%, 60%);
color: rgba(0, 0, 255, 0.1);
color: rgba(10,10,10,0.6);
color: rgba(11,10,9,0.6);
color: rgba(13,10,7,0.6);
color: rgba(16,10,4,0.6);
color: rgba(20,11,0,0.6);
}
#argb {
color: argb(rgba(0, 0, 255, 0.1));
}

View File

@@ -117,22 +117,22 @@
color: darken(#29332f, 100%); color: darken(#29332f, 100%);
} }
.spin { .spin {
color: spin(#555, 1%); color: spin(#555, 1);
color: spin(#555, 10%); color: spin(#555, -10);
color: spin(#555, 20%); color: spin(#555, 20);
color: spin(#555, 40%); color: spin(#555, -40);
color: spin(#555, 60%); color: spin(#555, 60);
color: spin(#555, 100%); color: spin(#555, -100);
color: spin(#000, 100%); color: spin(#000, 100);
color: spin(#000, 0%); color: spin(#000, 0);
color: spin(#fff, 100%); color: spin(#fff, 100);
color: spin(#fff, 0%); color: spin(#fff, 0);
color: spin(#29332f, 1%); color: spin(#29332f, 1);
color: spin(#29332f, 10%); color: spin(#29332f, -10);
color: spin(#29332f, 20%); color: spin(#29332f, 20);
color: spin(#29332f, 40%); color: spin(#29332f, -40);
color: spin(#29332f, 60%); color: spin(#29332f, 60);
color: spin(#29332f, 100%); color: spin(#29332f, 100);
} }
.grayscale { .grayscale {
color: grayscale(#000, 100%); color: grayscale(#000, 100%);
@@ -146,4 +146,21 @@
color: grayscale(#29332f, 60%); color: grayscale(#29332f, 60%);
color: grayscale(#29332f, 100%); color: grayscale(#29332f, 100%);
} }
.mix {
color: mix(#f00, #00f);
color: mix(#f00, #0ff);
color: mix(#f70, #0aa);
color: mix(#f00, #00f, 25%);
color: mix(#f00, #00f, 100%);
color: mix(#f00, #00f, 0%);
}
/*
Variables
*/
@base: #f04615;
.vars {
color: saturate(@base, 5%);
background-color: lighten(spin(@base, 8), 25%);
@new: hsl(hue(@base), 45%, 90%);
color: @new;
}

162
lesscpy/test/testcolor.py Normal file
View File

@@ -0,0 +1,162 @@
"""
lesscpy tests.
"""
import unittest
if __name__ == '__main__':
import bootstrap
from lesscpy.lessc import color
class TestLessColor(unittest.TestCase):
def setUp(self):
self.color = color.Color()
def test_rgb(self):
test = self.color.rgb
for r, g, b, v in [
(255,255,255,'#ffffff'),
(100,100,100,'#646464'),
(0,0,0,'#000000'),
('70%','70%','70%', '#b2b2b2'),
('1%','1%','1%', '#020202'),
('100%','100%','100%', '#ffffff'),
('0%','0%','0%', '#000000'),
]:
self.assertEqual(test(r, g, b), v)
for args in [
(255,255,256),
(0,-1,0),
('100%', '100%', 200),
('100%', '100%', '200%'),
]:
self.assertRaises(ValueError, test, args)
def test_rgba(self):
test = self.color.rgba
for r, g, b, a, v in [
(255,255,255,255,'#ffffffff'),
(100,100,100,100,'#64646464'),
(0,0,0,0,'#00000000'),
('70%','70%','70%', '70%', '#b2b2b2b2'),
('1%','1%','1%', '1%', '#02020202'),
('100%','100%','100%','100%', '#ffffffff'),
('0%','0%','0%','0%', '#00000000'),
]:
self.assertEqual(test(r, g, b, a), v)
for args in [
(255,255,255,256),
(0,0,0,-1),
('100%', '100%', '100%', 200),
('100%', '100%', '100%', '200%'),
]:
self.assertRaises(ValueError, test, args)
def test_hsl(self):
"""
"""
test = self.color.hsl
for h, s, l, v in [
(31, '1%', '4%', '#0a0a0a'),
(0, '100%', '100%', '#ffffff'),
(100, '100%', '100%', '#ffffff'),
(0, '0%', '0%', '#000000'),
(100, '0%', '0%', '#000000'),
]:
self.assertEqual(test(h, s, l), v)
def test_hsla(self):
test = self.color.hsla
for h, s, l, a, v in [
(31, '1%', '4%', '0%', 'rgba(10,10,10,0.0)'),
(31, '30%', '4%', '1%', 'rgba(13,10,7,0.01)'),
(31, '60%', '4%', '20%', 'rgba(16,10,4,0.2)'),
(31, '90%', '4%', '60%', 'rgba(19,11,1,0.6)'),
(31, '100%', '4%', '100%', 'rgba(20,11,0,1.0)'),
]:
self.assertEqual(test(h, s, l, a), v)
def test_fmt(self):
test = self.color.fmt
self.assertEqual(test('#000'), '#000000')
self.assertEqual(test('#000000'), '#000000')
self.assertEqual(test('#0000'), '#00000000')
self.assertEqual(test('#00000000'), '#00000000')
self.assertEqual(test('#AAA'), '#aaaaaa')
self.assertEqual(test('#Abc'), '#aabbcc')
self.assertEqual(test('#AbCdEf'), '#abcdef')
self.assertRaises(ValueError, test, '#xxx')
self.assertRaises(ValueError, test, None)
self.assertRaises(ValueError, test, 'aabbcc')
self.assertRaises(ValueError, test, '#4aabbcc')
def test_saturate(self):
test = self.color.saturate
for c, p, v in [
('#555', '1%', '#565454'),
('#555', '10%', '#5e4c4c'),
('#555', '20%', '#664444'),
('#555', '40%', '#773333'),
('#555', '60%', '#882222'),
('#555', '100%', '#aa0000'),
('#000', '100%', '#000000'),
('#000', '0%', '#000000'),
('#fff', '100%', '#ffffff'),
('#fff', '0%', '#ffffff'),
('#29332f', '1%', '#29332f'),
('#29332f', '10%', '#243830'),
('#29332f', '20%', '#203c31'),
('#29332f', '40%', '#174533'),
('#29332f', '60%', '#0d4f35'),
('#29332f', '100%', '#005c37'),
]:
self.assertEqual(test(c, p), v, v)
def test_desaturate(self):
test = self.color.desaturate
for c, p, v in [
('#555', '1%', '#555555'),
('#555', '10%', '#555555'),
('#555', '20%', '#555555'),
('#555', '40%', '#555555'),
('#555', '60%', '#555555'),
('#555', '100%', '#555555'),
('#000', '100%', '#000000'),
('#000', '0%', '#000000'),
('#fff', '100%', '#ffffff'),
('#fff', '0%', '#ffffff'),
('#29332f', '1%', '#29332f'),
('#29332f', '10%', '#2e2e2e'),
('#29332f', '20%', '#2e2e2e'),
('#29332f', '40%', '#2e2e2e'),
('#29332f', '60%', '#2e2e2e'),
('#29332f', '100%', '#2e2e2e'),
]:
self.assertEqual(test(c, p), v, v)
def test_spin(self):
test = self.color.spin
for c, p, v in [
('#555', '1%', '#555555'),
('#555', '10%', '#555555'),
('#555', '20%', '#555555'),
('#555', '40%', '#555555'),
('#555', '60%', '#555555'),
('#555', '100%', '#555555'),
('#000', '100%', '#000000'),
('#000', '0%', '#000000'),
('#fff', '100%', '#ffffff'),
('#fff', '0%', '#ffffff'),
('#29332f', '1%', '#29332f'),
('#29332f', '10%', '#293331'),
('#29332f', '20%', '#293332'),
('#29332f', '40%', '#293033'),
('#29332f', '60%', '#292d33'),
('#29332f', '100%', '#2c2933'),
]:
self.assertEqual(test(c, p), v, v)
if __name__ == '__main__':
unittest.main()