aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtests/test_rgba.py8
-rwxr-xr-xthcolor/_builtin/_css.py188
-rwxr-xr-xthcolor/_builtin/_default.py10
-rwxr-xr-xthcolor/_color.py25
-rwxr-xr-xthcolor/_ref.py7
5 files changed, 152 insertions, 86 deletions
diff --git a/tests/test_rgba.py b/tests/test_rgba.py
index f6af1f9..07614e2 100755
--- a/tests/test_rgba.py
+++ b/tests/test_rgba.py
@@ -19,7 +19,13 @@ from thcolor import Color
(' rgb (1,22, 242 , 50.0% )', ( 1, 22, 242, 0.5)),
('rgba(1,22,242,0.500)', ( 1, 22, 242, 0.5)),
('rbga(5, 7)', ( 5, 0, 7, 1.0)),
- ('hsl(0, 1,50.0%)', (255, 0, 0, 1.0))))
+ ('hsl(0, 1,50.0%)', (255, 0, 0, 1.0)),
+ ('hls(0 / 1 0.5 , 0.2)', (255, 0, 0, 0.2)),
+ ('hwb(0 0% 0)', (255, 0, 0, 1.0)),
+ ('hbw(127 .5)', (128, 255, 142, 1.0)),
+ ('gray(100)', (100, 100, 100, 1.0)),
+ ('gray(100 / 55 %)', (100, 100, 100, 0.55)),
+))
def test_rgba(test_input, expected):
assert Color.from_text(test_input).rgba() == expected
diff --git a/thcolor/_builtin/_css.py b/thcolor/_builtin/_css.py
index a875907..45449ed 100755
--- a/thcolor/_builtin/_css.py
+++ b/thcolor/_builtin/_css.py
@@ -20,6 +20,10 @@ class CSS1Reference(_Reference):
""" Named colors from CSS Level 1:
https://www.w3.org/TR/CSS1/ """
+ number = _Reference.number
+ percentage = _Reference.percentage
+ color = _Reference.color
+
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -55,6 +59,45 @@ class CSS1Reference(_Reference):
except:
return super()._color(name)
+ # ---
+ # Utilities.
+ # ---
+
+ def _rgb(self, rgba, rgb_indexes):
+ r, g, b, alpha = rgba
+ ri, gi, bi = rgb_indexes
+
+ try:
+ r = r.to_byte()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(ri, str(e))
+
+ try:
+ g = g.to_byte()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(gi, str(e))
+
+ try:
+ b = b.to_byte()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(bi, str(e))
+
+ try:
+ alpha = alpha.to_factor()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(3, str(e))
+
+ return _Reference.color(_Color(_Color.Type.RGB, r, g, b, alpha))
+
+ # ---
+ # Functions.
+ # ---
+
+ def rgb(self, r: number | percentage,
+ g: number | percentage = number(0),
+ b: number | percentage = number(0)):
+ return self._rgb((r, g, b, 1.0), (0, 1, 2))
+
class CSS2Reference(CSS1Reference):
""" Named colors from CSS Level 2 (Revision 1):
https://www.w3.org/TR/CSS2/ """
@@ -79,6 +122,11 @@ class CSS3Reference(CSS2Reference):
""" Named colors from CSS Color Module Level 3:
https://drafts.csswg.org/css-color-3/ """
+ number = _Reference.number
+ percentage = _Reference.percentage
+ angle = _Reference.angle
+ color = _Reference.color
+
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -224,61 +272,10 @@ class CSS3Reference(CSS2Reference):
except:
return super()._color(name)
-class CSS4Reference(CSS3Reference):
- """ Named colors from CSS Color Module Level 4:
- https://drafts.csswg.org/css-color/ """
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- number = _Reference.number
- percentage = _Reference.percentage
- angle = _Reference.angle
- color = _Reference.color
-
- # ---
- # Named colors.
- # ---
-
- __colors = {
- 'rebeccapurple': _rgb('#663399')}
-
- def _color(self, name):
- try:
- return self.__colors[name]
- except:
- return super()._color(name)
-
# ---
# Utilities.
# ---
- def _rgb(self, rgba, rgb_indexes):
- r, g, b, alpha = rgba
- ri, gi, bi = rgb_indexes
-
- try:
- r = r.to_byte()
- except ValueError as e:
- raise _InvalidArgumentValueError(ri, str(e))
-
- try:
- g = g.to_byte()
- except ValueError as e:
- raise _InvalidArgumentValueError(gi, str(e))
-
- try:
- b = b.to_byte()
- except ValueError as e:
- raise _InvalidArgumentValueError(bi, str(e))
-
- try:
- alpha = alpha.to_factor()
- except ValueError as e:
- raise _InvalidArgumentValueError(3, str(e))
-
- return _Reference.color(_Color(_Color.Type.RGB, r, g, b, alpha))
-
def _hsl(self, hsla, hsl_indexes):
h, s, l, alpha = hsla
hi, si, li = hsl_indexes
@@ -305,6 +302,57 @@ class CSS4Reference(CSS3Reference):
return _Reference.color(_Color(_Color.Type.HSL, h, s, l, alpha))
+ # ---
+ # Functions.
+ # ---
+
+ def rgb(self, r: number | percentage,
+ g: number | percentage = number(0), b: number | percentage = number(0),
+ alpha: number | percentage = number(1.0)):
+ return self._rgb((r, g, b, alpha), (0, 1, 2))
+
+ def rgba(self, r: number | percentage,
+ g: number | percentage = number(0), b: number | percentage = number(0),
+ alpha: number | percentage = number(1.0)):
+ return self._rgb((r, g, b, alpha), (0, 1, 2))
+
+ def hsl(self, h: number | angle, s: number | percentage,
+ l: number | percentage, alpha: number | percentage = number(1.0)):
+ return self._hsl((h, s, l, alpha), (0, 1, 2))
+
+ def hsla(self, h: number | angle, s: number | percentage,
+ l: number | percentage, alpha: number | percentage = number(1.0)):
+ return self._hsl((h, s, l, alpha), (0, 1, 2))
+
+class CSS4Reference(CSS3Reference):
+ """ Named colors from CSS Color Module Level 4:
+ https://drafts.csswg.org/css-color/ """
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ number = _Reference.number
+ percentage = _Reference.percentage
+ angle = _Reference.angle
+ color = _Reference.color
+
+ # ---
+ # Named colors.
+ # ---
+
+ __colors = {
+ 'rebeccapurple': _rgb('#663399')}
+
+ def _color(self, name):
+ try:
+ return self.__colors[name]
+ except:
+ return super()._color(name)
+
+ # ---
+ # Utilities.
+ # ---
+
def _hwb(self, hwba, hwb_indexes):
h, w, b, alpha = hwba
hi, wi, bi = hwb_indexes
@@ -335,31 +383,28 @@ class CSS4Reference(CSS3Reference):
# Functions.
# ---
- def rgb(self, r: number | percentage,
- g: number | percentage = number(0), b: number | percentage = number(0),
+ def hwb(self, h: number | angle, w: number | percentage = number(0),
+ b: number | percentage = number(0),
alpha: number | percentage = number(1.0)):
- return self._rgb((r, g, b, alpha), (0, 1, 2))
+ return self._hwb((h, w, b, alpha), (0, 1, 2))
- def rgba(self, r: number | percentage,
- g: number | percentage = number(0), b: number | percentage = number(0),
+ def hwba(self, h: number | angle, w: number | percentage = number(0),
+ b: number | percentage = number(0),
alpha: number | percentage = number(1.0)):
- return self._rgb((r, g, b, alpha), (0, 1, 2))
-
- def hsl(self, h: number | angle, s: number | percentage,
- l: number | percentage, alpha: number | percentage = number(1.0)):
- return self._hsl((h, s, l, alpha), (0, 1, 2))
+ return self._hwb((h, w, b, alpha), (0, 1, 2))
- def hsla(self, h: number | angle, s: number | percentage,
- l: number | percentage, alpha: number | percentage = number(1.0)):
- return self._hsl((h, s, l, alpha), (0, 1, 2))
+ def gray(self, g: number | percentage, alpha: percentage = number(1.0)):
+ try:
+ g = g.to_byte()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(0, str(e))
- def hwb(self, h: number | angle, w: number | percentage,
- b: number | percentage, alpha: number | percentage = number(1.0)):
- return self._hwb((h, w, b, alpha), (0, 1, 2))
+ try:
+ alpha = alpha.to_factor()
+ except ValueError as e:
+ raise _InvalidArgumentValueError(1, str(e))
- def hwba(self, h: number | angle, w: number | percentage,
- b: number | percentage, alpha: number | percentage = number(1.0)):
- return self._hwb((h, w, b, alpha), (0, 1, 2))
+ return _Reference.color(_Color(_Color.Type.RGB, g, g, g, alpha))
def lab(self, l: number, a: number, b: number,
alpha: percentage = number(1.0)):
@@ -369,7 +414,4 @@ class CSS4Reference(CSS3Reference):
alpha: percentage = number(1.0)):
raise NotImplementedError
- def gray(self, g: number, alpha: percentage = number(1.0)):
- raise NotImplementedError
-
# End of file.
diff --git a/thcolor/_builtin/_default.py b/thcolor/_builtin/_default.py
index d6004be..c34243b 100755
--- a/thcolor/_builtin/_default.py
+++ b/thcolor/_builtin/_default.py
@@ -84,4 +84,14 @@ class DefaultReference(_CSS4Reference):
s: number | percentage, alpha: number | percentage = number(1.0)):
return self._hsl((h, s, l, alpha), (0, 2, 1))
+ def hbw(self, h: number | angle, b: number | percentage = number(0),
+ w: number | percentage = number(0),
+ alpha: number | percentage = number(1.0)):
+ return self._hwb((h, w, b, alpha), (0, 2, 1))
+
+ def hbwa(self, h: number | angle, b: number | percentage = number(0),
+ w: number | percentage = number(0),
+ alpha: number | percentage = number(1.0)):
+ return self._hwb((h, w, b, alpha), (0, 2, 1))
+
# End of file.
diff --git a/thcolor/_color.py b/thcolor/_color.py
index 76dc505..04dd19f 100755
--- a/thcolor/_color.py
+++ b/thcolor/_color.py
@@ -302,16 +302,12 @@ class Color:
if self._type == Color.Type.RGB:
return (self._r, self._g, self._b)
elif self._type == Color.Type.HSL:
- r, g, b = _hls_to_rgb(self._hue.turns % 1, self._lgt, self._sat)
- r *= 255
- g *= 255
- b *= 255
+ r, g, b = map(lambda x: int(x * 255),
+ _hls_to_rgb(self._hue.turns % 1, self._lgt, self._sat))
return (r, g, b)
elif self._type == Color.Type.HWB:
- r, g, b = _hwb_to_rgb(self._hue.turns % 1, self._wht, self._blk)
- r *= 255
- g *= 255
- b *= 255
+ r, g, b = map(lambda x: int(x * 255),
+ _hwb_to_rgb(self._hue.turns % 1, self._wht, self._blk))
return (r, g, b)
raise ValueError(f"color type {self._type} doesn't translate to rgb")
@@ -333,6 +329,7 @@ class Color:
# notation if the alpha value isn't 1.0.
r, g, b, a = self.rgba()
+ a = round(a, 3)
yield f'#{r:02X}{g:02X}{b:02X}'
if a < 1.0:
@@ -344,11 +341,19 @@ class Color:
if self._type == Type.HSL:
s = round(self._sat, 5) * 100
l = round(self._lgt, 5) * 100
- yield f'hsl({self._hue}, {s}%, {l}%)'
+
+ if a < 1.0:
+ yield f'hsla({self._hue}, {s}%, {l}%, {a})'
+ else:
+ yield f'hsl({self._hue}, {s}%, {l}%)'
elif self._type == Type.HWB:
w = round(self._wht, 5) * 100
b = round(self._blk, 5) * 100
- yield f'hwb({self._hue}, {w}%, {b}%)'
+
+ if a < 1.0:
+ yield f'hwba({self._hue}, {w}%, {b}%, {a})'
+ else:
+ yield f'hwb({self._hue}, {w}%, {b}%)'
return list(statements())
diff --git a/thcolor/_ref.py b/thcolor/_ref.py
index 5bc51c1..9c8a017 100755
--- a/thcolor/_ref.py
+++ b/thcolor/_ref.py
@@ -139,13 +139,16 @@ class Reference:
def __init__(self, value):
self._value = value
- assert 0 <= value <= 100
+ if value < 0:
+ value = 0
+
+ # value can actually be more than 100.
def __repr__(self):
return f"{self._value} %"
def to_byte(self):
- return int(self._value / 100 * 255)
+ return int(min(self._value / 100, 1.0) * 255)
def to_factor(self):
try: