aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Touhey <thomas@touhey.fr>2019-05-09 23:48:12 +0200
committerThomas Touhey <thomas@touhey.fr>2019-05-09 23:48:12 +0200
commita3a97576e40749ae6ba6cfa1735aa05e63cc2905 (patch)
tree4d88c4be94714cf35d59c1c6875d6cf7af6c58d0
parent7d914122185bac74146963bb8e378dee2e10f4fb (diff)
Started adding ncol support
-rwxr-xr-xtests/test_text.py10
-rwxr-xr-xthcolor/_builtin/_css.py10
-rwxr-xr-xthcolor/_builtin/_default.py68
-rwxr-xr-xthcolor/_color.py44
-rwxr-xr-xthcolor/_ref.py2
5 files changed, 127 insertions, 7 deletions
diff --git a/tests/test_text.py b/tests/test_text.py
index e5a7d4c..a923842 100755
--- a/tests/test_text.py
+++ b/tests/test_text.py
@@ -28,13 +28,19 @@ def _deg(value):
('hbw(127 .5)', (128, 255, 142, 1.00)),
('gray(100)', (100, 100, 100, 1.00)),
('gray(100 / 55 %)', (100, 100, 100, 0.55)),
+ ('gray(red( #123456 )/0.2/)', ( 18, 18, 18, 0.20)),
+ ('B20 50% 32%', (137, 128, 173, 1.00)),
))
def test_rgba(test_input, expected):
assert Color.from_text(test_input).rgba() == expected
@pytest.mark.parametrize('test_input,expected', (
- ('darker(10%, hsl(0, 1, 50.0%))', (_deg(0), 1.0, 0.4, 1.00)),
- ('lighter(50%, hsl(0, 1, 60.0%))', (_deg(0), 1.0, 1.0, 1.00)),
+ ('darker(10%, hsl(0, 1, 50.0%))', (_deg( 0), 1.00, 0.40, 1.00)),
+ ('lighter(50%, hsl(0, 1, 60.0%))', (_deg( 0), 1.00, 1.00, 1.00)),
+ ('saturate(10%, hls(0, 1, 85.0%))', (_deg( 0), 0.95, 1.00, 1.00)),
+ ('desaturate(10%, hls(0, 1, 5%, 0.2))', (_deg( 0), 0.00, 1.00, 0.20)),
+ ('rgba(255, 0, 0, 20 %)', (_deg( 0), 0.50, 1.00, 0.20)),
+ ('Y40, 33%, 55%', (_deg(84), 0.15, 0.39, 1.00)),
))
def test_hsla(test_input, expected):
assert Color.from_text(test_input).hsla() == expected
diff --git a/thcolor/_builtin/_css.py b/thcolor/_builtin/_css.py
index 45449ed..06bf539 100755
--- a/thcolor/_builtin/_css.py
+++ b/thcolor/_builtin/_css.py
@@ -393,7 +393,8 @@ class CSS4Reference(CSS3Reference):
alpha: number | percentage = number(1.0)):
return self._hwb((h, w, b, alpha), (0, 1, 2))
- def gray(self, g: number | percentage, alpha: percentage = number(1.0)):
+ def gray(self, g: number | percentage,
+ alpha: number | percentage = number(1.0)):
try:
g = g.to_byte()
except ValueError as e:
@@ -408,10 +409,17 @@ class CSS4Reference(CSS3Reference):
def lab(self, l: number, a: number, b: number,
alpha: percentage = number(1.0)):
+ # TODO: lab
raise NotImplementedError
def lch(self, l: number, c: number, h: number | angle,
alpha: percentage = number(1.0)):
+ # TODO: lch
+ raise NotImplementedError
+
+ def cmyk(self, c: percentage, m: percentage = percentage(0),
+ y: percentage = percentage(0), k = percentage(0)):
+ # TODO: cmyk
raise NotImplementedError
# End of file.
diff --git a/thcolor/_builtin/_default.py b/thcolor/_builtin/_default.py
index 8ae5768..b047519 100755
--- a/thcolor/_builtin/_default.py
+++ b/thcolor/_builtin/_default.py
@@ -24,7 +24,7 @@ class DefaultReference(_CSS4Reference):
color = _Reference.color
# ---
- # Utilities.
+ # RGB functions.
# ---
def rbg(self, r: number | percentage,
@@ -77,6 +77,10 @@ class DefaultReference(_CSS4Reference):
alpha: number | percentage = number(1.0)):
return self._rgb((r, g, b, alpha), (1, 0, 2))
+ # ---
+ # HLS and HWB aliases.
+ # ---
+
def hls(self, h: number | angle, l: number | percentage,
s: number | percentage, alpha: number | percentage = number(1.0)):
return self._hsl((h, s, l, alpha), (0, 2, 1))
@@ -95,6 +99,26 @@ class DefaultReference(_CSS4Reference):
alpha: number | percentage = number(1.0)):
return self._hwb((h, w, b, alpha), (0, 2, 1))
+ # ---
+ # Get the RGB components of a color.
+ # ---
+
+ def red(self, col: color) -> number:
+ r, g, b = col.to_color().rgb()
+ return _Reference.number(r)
+
+ def green(self, col: color) -> number:
+ r, g, b = col.to_color().rgb()
+ return _Reference.number(g)
+
+ def blue(self, col: color) -> number:
+ r, g, b = col.to_color().rgb()
+ return _Reference.number(b)
+
+ # ---
+ # Manage the lightness and saturation for HSL colors.
+ # ---
+
def darker(self, by: number | percentage, col: color) -> color:
try:
by = by.to_factor()
@@ -127,4 +151,46 @@ class DefaultReference(_CSS4Reference):
return _Reference.color(_Color(_Color.Type.HSL, h, s, l, a))
+ def desaturate(self, by: number | percentage, col: color) -> color:
+ try:
+ by = by.to_factor()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(0, str(e))
+
+ try:
+ col = col.to_color()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(0, str(e))
+
+ h, l, s, a = col.hlsa()
+ s = max(s - by, 0.0)
+
+ return _Reference.color(_Color(_Color.Type.HSL, h, s, l, a))
+
+ def saturate(self, by: number | percentage, col: color) -> color:
+ try:
+ by = by.to_factor()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(0, str(e))
+
+ try:
+ col = col.to_color()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(0, str(e))
+
+ h, l, s, a = col.hlsa()
+ s = min(s + by, 1.0)
+
+ return _Reference.color(_Color(_Color.Type.HSL, h, s, l, a))
+
+ # ---
+ # Others.
+ # ---
+
+ def ncol(self, col: color) -> color:
+ # Compatibility with w3color.js! NCols are managed directly without
+ # the function, so the functio doesn't do anything.
+
+ return col
+
# End of file.
diff --git a/thcolor/_color.py b/thcolor/_color.py
index 7f69d90..63b35d5 100755
--- a/thcolor/_color.py
+++ b/thcolor/_color.py
@@ -41,6 +41,7 @@ _ColorPattern = _re.compile(r"""
(?P<agl_typ>deg|grad|rad|turn))
| ((?P<per>[0-9]+(\.[0-9]*)? | \.[0-9]+) \s* \%)
| (?P<num>[0-9]+(\.[0-9]*)? | \.[0-9]+)
+ | (?P<ncol>[RYGCBM] [0-9]{0,2})
| (\# (?P<hex>[0-9a-f]{3} | [0-9a-f]{4} | [0-9a-f]{6} | [0-9a-f]{8}))
| ((?P<name>[a-z]([a-z0-9\s_-]*[a-z0-9_-])?)
( \s* \( \s* (?P<arg> (?0)? ) \s* \) )?)
@@ -396,12 +397,12 @@ class Color:
""" Get the (hue, saturation, lightness) components of the color. """
if self._type == Color.Type.RGB:
- h, s, l = _rgb_to_hsl(self._r, self._g, self._b)
+ h, l, s = _rgb_to_hls(self._r, self._g, self._b)
return (_Angle(_Angle.Type.TURN, h), s, l)
elif self._type == Color.Type.HSL:
return (self._hue, self._sat, self._lgt)
elif self._type == Color.Type.HWB:
- h, s, l = _hwb_to_hsl(self._hue.turns % 1, self._wht, self._blk)
+ h, l, s = _hwb_to_hls(self._hue.turns % 1, self._wht, self._blk)
return (_Angle(_Angle.Type.TURN, h), s, l)
raise ValueError(f"color type {self._type} doesn't translate to hsl")
@@ -602,6 +603,45 @@ class Color:
raise _ColorExpressionDecodingError("not implemented",
column = column, func = name)
else:
+ if match['ncol']:
+ # The match is probably a natural color (ncol), we ought
+ # to parse it and get the following arguments or, if
+ # anything is invalid, to treat it as a color name.
+
+ name = match['ncol']
+
+ # First, get the letter and proportion.
+
+ letter = name[0]
+ number = float(name[1:])
+
+ if number >= 0 and number < 100:
+ # Get the following arguments and check.
+
+ args = recurse(column + match.start('nextargs'),
+ _ColorPattern.fullmatch(match['nextargs'] or ""))
+
+ try:
+ assert len(args) >= 2
+ w = args[0].value.to_factor()
+ b = args[1].value.to_factor()
+ except:
+ w = 0
+ b = 0
+ else:
+ args = args[2:]
+
+ # Calculate the color and return the args.
+
+ color = Color(Color.Type.HWB,
+ _Angle(_Angle.Type.DEG, 'RYGCBM'.find(letter) \
+ * 60 + number / 100 * 60), w, b)
+
+ # And finally, return the args.
+
+ return (argument(column, _Reference.color(color)),) \
+ + args
+
# The matched value is a named color.
name = match['name']
diff --git a/thcolor/_ref.py b/thcolor/_ref.py
index 83cf9b6..19a469c 100755
--- a/thcolor/_ref.py
+++ b/thcolor/_ref.py
@@ -268,7 +268,7 @@ class Reference:
# a color to manage number colors using the
# Netscape transformation such as '123'.
- if color in exp:
+ if Reference.color in exp:
try:
args[-1] = arg.to_color()
except: