1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 '''
31 Provide some short-hand colour definitions for cairo.
32
33 As far as I can tell, cairo uses pre-multiplied alpha -
34 http://en.wikipedia.org/wiki/Alpha_compositing
35 '''
36
37
38 from collections import namedtuple
39 from operator import itemgetter
47 return setter
48
49
50
51
52 -class Colour(namedtuple('BaseColour', 'r g b a')):
53
55 a = min(1, max(0, a))
56 r = min(a, max(0, r))
57 g = min(a, max(0, g))
58 b = min(a, max(0, b))
59 return super(Colour, cls).__new__(cls, r, g, b, a)
60
61 r = property(itemgetter(0), _replace(0))
62 g = property(itemgetter(1), _replace(1))
63 b = property(itemgetter(2), _replace(2))
64 a = property(itemgetter(3), _replace(3))
65
66 @staticmethod
69
71 '''
72 Convert to an RGB triplet (alpha is not removed).
73 '''
74 return (self.r, self.g, self.b)
75
77 '''
78 Scale the colour by some factor.
79
80 If factor is a single value, it is applied only to the RGB components;
81 if it is a pair then the second value is applied to alpha (and
82 folded in to RGB too). So 0.5 would reduce RGB by half; (1, 0.5)
83 would reduce alpha by half (and scale RGB correspondingly); (0.5, 0.5)
84 would scale RGB *and* reduce alpha (so pre-multiplied RGB would be
85 numerically scaled by 0.25).
86
87 After scaling, values are clipped within (0, 1).
88 '''
89 r, g, b, a = self
90 try:
91 frgb, fa = factor
92 frgb *= fa
93 r *= frgb
94 g *= frgb
95 b *= frgb
96 a *= fa
97 except TypeError:
98 r *= factor
99 g *= factor
100 b *= factor
101 return Colour(r, g, b, a)
102
104 '''
105 The same colour, but with alpha forced to 1.
106 '''
107 return Colour(self.r / self.a, self.g / self.a, self.b / self.a)
108
119
120
121 BLACK = Colour(0, 0, 0)
122 RED = Colour(1, 0, 0)
123 GREEN = Colour(0, 1, 0)
124 BLUE = Colour(0, 0, 1)
125 YELLOW = Colour(1, 1, 0)
126 CYAN = Colour(0, 1, 1)
127 MAGENTA = Colour(1, 0, 1)
128 WHITE = Colour(1, 1, 1)
129