1#!/usr/bin/python 2 3# Copyright 2011 Software Freedom Conservancy. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17RGB_PATTERN = r"^\s*rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)\s*$" 18RGB_PCT_PATTERN = r"^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$" 19RGBA_PATTERN = r"^\s*rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0\.\d+)\s*\)\s*$" 20RGBA_PCT_PATTERN = r"^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(0|1|0\.\d+)\s*\)\s*$" 21HEX_PATTERN = r"#([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})" 22HEX3_PATTERN = r"#([A-Fa-f0-9])([A-Fa-f0-9])([A-Fa-f0-9])" 23HSL_PATTERN = r"^\s*hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)\s*$" 24HSLA_PATTERN = r"^\s*hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(0|1|0\.\d+)\s*\)\s*$" 25 26 27class Color(object): 28 """ 29 Color conversion support class 30 31 Example: 32 33 .. code-block:: python 34 35 from selenium.webdriver.support.color import Color 36 37 print Color.from_string('#00ff33').rgba 38 print Color.from_string('rgb(1, 255, 3)').hex 39 print Color.from_string('blue').rgba 40 """ 41 42 @staticmethod 43 def from_string(str_): 44 import re 45 46 class Matcher(object): 47 def __init__(self): 48 self.match_obj = None 49 50 def match(self, pattern, str_): 51 self.match_obj = re.match(pattern, str_) 52 return self.match_obj 53 54 @property 55 def groups(self): 56 return () if self.match_obj is None else self.match_obj.groups() 57 58 m = Matcher() 59 60 if m.match(RGB_PATTERN, str_): 61 return Color(*m.groups) 62 elif m.match(RGB_PCT_PATTERN, str_): 63 rgb = tuple([float(each) / 100 * 255 for each in m.groups]) 64 return Color(*rgb) 65 elif m.match(RGBA_PATTERN, str_): 66 return Color(*m.groups) 67 elif m.match(RGBA_PCT_PATTERN, str_): 68 rgba = tuple([float(each) / 100 * 255 for each in m.groups[:3]] + [m.groups[3]]) 69 return Color(*rgba) 70 elif m.match(HEX_PATTERN, str_): 71 rgb = tuple([int(each, 16) for each in m.groups]) 72 return Color(*rgb) 73 elif m.match(HEX3_PATTERN, str_): 74 rgb = tuple([int(each * 2, 16) for each in m.groups]) 75 return Color(*rgb) 76 elif m.match(HSL_PATTERN, str_) or m.match(HSLA_PATTERN, str_): 77 return Color._from_hsl(*m.groups) 78 elif str_.upper() in Colors.keys(): 79 return Colors[str_.upper()] 80 else: 81 raise ValueError("Could not convert %s into color" % str_) 82 83 @staticmethod 84 def _from_hsl(h, s, l, a=1): 85 h = float(h) / 360 86 s = float(s) / 100 87 l = float(l) / 100 88 89 if s == 0: 90 r = l 91 g = r 92 b = r 93 else: 94 luminocity2 = l * (1 + s) if l < 0.5 else l + s - l * s 95 luminocity1 = 2 * l - luminocity2 96 97 def hue_to_rgb(lum1, lum2, hue): 98 if hue < 0.0: 99 hue += 1 100 if hue > 1.0: 101 hue -= 1 102 103 if hue < 1.0 / 6.0: 104 return (lum1 + (lum2 - lum1) * 6.0 * hue) 105 elif hue < 1.0 / 2.0: 106 return lum2 107 elif hue < 2.0 / 3.0: 108 return lum1 + (lum2 - lum1) * ((2.0 / 3.0) - hue) * 6.0 109 else: 110 return lum1 111 112 r = hue_to_rgb(luminocity1, luminocity2, h + 1.0 / 3.0) 113 g = hue_to_rgb(luminocity1, luminocity2, h) 114 b = hue_to_rgb(luminocity1, luminocity2, h - 1.0 / 3.0) 115 116 return Color(r * 256, g * 256, b * 256, a) 117 118 def __init__(self, red, green, blue, alpha=1): 119 self.red = int(red) 120 self.green = int(green) 121 self.blue = int(blue) 122 self.alpha = float(alpha) or 0 123 124 @property 125 def rgb(self): 126 return "rgb(%d, %d, %d)" % (self.red, self.green, self.blue) 127 128 @property 129 def rgba(self): 130 a = "1" if self.alpha == 1 else str(self.alpha) 131 return "rgba(%d, %d, %d, %s)" % (self.red, self.green, self.blue, a) 132 133 @property 134 def hex(self): 135 return "#%02x%02x%02x" % (self.red, self.green, self.blue) 136 137 def __eq__(self, other): 138 if isinstance(other, Color): 139 return self.rgba == other.rgba 140 return NotImplemented 141 142 def __ne__(self, other): 143 result = self.__eq__(other) 144 if result is NotImplemented: 145 return result 146 return not result 147 148 def __hash__(self): 149 return hash((self.red, self.green, self.blue, self.alpha)) 150 151 152# Basic, extended and transparent colour keywords as defined by the W3C HTML4 spec 153# See http://www.w3.org/TR/css3-color/#html4 154Colors = { 155 "TRANSPARENT": Color(0, 0, 0, 0), 156 "ALICEBLUE": Color(240, 248, 255), 157 "ANTIQUEWHITE": Color(250, 235, 215), 158 "AQUA": Color(0, 255, 255), 159 "AQUAMARINE": Color(127, 255, 212), 160 "AZURE": Color(240, 255, 255), 161 "BEIGE": Color(245, 245, 220), 162 "BISQUE": Color(255, 228, 196), 163 "BLACK": Color(0, 0, 0), 164 "BLANCHEDALMOND": Color(255, 235, 205), 165 "BLUE": Color(0, 0, 255), 166 "BLUEVIOLET": Color(138, 43, 226), 167 "BROWN": Color(165, 42, 42), 168 "BURLYWOOD": Color(222, 184, 135), 169 "CADETBLUE": Color(95, 158, 160), 170 "CHARTREUSE": Color(127, 255, 0), 171 "CHOCOLATE": Color(210, 105, 30), 172 "CORAL": Color(255, 127, 80), 173 "CORNFLOWERBLUE": Color(100, 149, 237), 174 "CORNSILK": Color(255, 248, 220), 175 "CRIMSON": Color(220, 20, 60), 176 "CYAN": Color(0, 255, 255), 177 "DARKBLUE": Color(0, 0, 139), 178 "DARKCYAN": Color(0, 139, 139), 179 "DARKGOLDENROD": Color(184, 134, 11), 180 "DARKGRAY": Color(169, 169, 169), 181 "DARKGREEN": Color(0, 100, 0), 182 "DARKGREY": Color(169, 169, 169), 183 "DARKKHAKI": Color(189, 183, 107), 184 "DARKMAGENTA": Color(139, 0, 139), 185 "DARKOLIVEGREEN": Color(85, 107, 47), 186 "DARKORANGE": Color(255, 140, 0), 187 "DARKORCHID": Color(153, 50, 204), 188 "DARKRED": Color(139, 0, 0), 189 "DARKSALMON": Color(233, 150, 122), 190 "DARKSEAGREEN": Color(143, 188, 143), 191 "DARKSLATEBLUE": Color(72, 61, 139), 192 "DARKSLATEGRAY": Color(47, 79, 79), 193 "DARKSLATEGREY": Color(47, 79, 79), 194 "DARKTURQUOISE": Color(0, 206, 209), 195 "DARKVIOLET": Color(148, 0, 211), 196 "DEEPPINK": Color(255, 20, 147), 197 "DEEPSKYBLUE": Color(0, 191, 255), 198 "DIMGRAY": Color(105, 105, 105), 199 "DIMGREY": Color(105, 105, 105), 200 "DODGERBLUE": Color(30, 144, 255), 201 "FIREBRICK": Color(178, 34, 34), 202 "FLORALWHITE": Color(255, 250, 240), 203 "FORESTGREEN": Color(34, 139, 34), 204 "FUCHSIA": Color(255, 0, 255), 205 "GAINSBORO": Color(220, 220, 220), 206 "GHOSTWHITE": Color(248, 248, 255), 207 "GOLD": Color(255, 215, 0), 208 "GOLDENROD": Color(218, 165, 32), 209 "GRAY": Color(128, 128, 128), 210 "GREY": Color(128, 128, 128), 211 "GREEN": Color(0, 128, 0), 212 "GREENYELLOW": Color(173, 255, 47), 213 "HONEYDEW": Color(240, 255, 240), 214 "HOTPINK": Color(255, 105, 180), 215 "INDIANRED": Color(205, 92, 92), 216 "INDIGO": Color(75, 0, 130), 217 "IVORY": Color(255, 255, 240), 218 "KHAKI": Color(240, 230, 140), 219 "LAVENDER": Color(230, 230, 250), 220 "LAVENDERBLUSH": Color(255, 240, 245), 221 "LAWNGREEN": Color(124, 252, 0), 222 "LEMONCHIFFON": Color(255, 250, 205), 223 "LIGHTBLUE": Color(173, 216, 230), 224 "LIGHTCORAL": Color(240, 128, 128), 225 "LIGHTCYAN": Color(224, 255, 255), 226 "LIGHTGOLDENRODYELLOW": Color(250, 250, 210), 227 "LIGHTGRAY": Color(211, 211, 211), 228 "LIGHTGREEN": Color(144, 238, 144), 229 "LIGHTGREY": Color(211, 211, 211), 230 "LIGHTPINK": Color(255, 182, 193), 231 "LIGHTSALMON": Color(255, 160, 122), 232 "LIGHTSEAGREEN": Color(32, 178, 170), 233 "LIGHTSKYBLUE": Color(135, 206, 250), 234 "LIGHTSLATEGRAY": Color(119, 136, 153), 235 "LIGHTSLATEGREY": Color(119, 136, 153), 236 "LIGHTSTEELBLUE": Color(176, 196, 222), 237 "LIGHTYELLOW": Color(255, 255, 224), 238 "LIME": Color(0, 255, 0), 239 "LIMEGREEN": Color(50, 205, 50), 240 "LINEN": Color(250, 240, 230), 241 "MAGENTA": Color(255, 0, 255), 242 "MAROON": Color(128, 0, 0), 243 "MEDIUMAQUAMARINE": Color(102, 205, 170), 244 "MEDIUMBLUE": Color(0, 0, 205), 245 "MEDIUMORCHID": Color(186, 85, 211), 246 "MEDIUMPURPLE": Color(147, 112, 219), 247 "MEDIUMSEAGREEN": Color(60, 179, 113), 248 "MEDIUMSLATEBLUE": Color(123, 104, 238), 249 "MEDIUMSPRINGGREEN": Color(0, 250, 154), 250 "MEDIUMTURQUOISE": Color(72, 209, 204), 251 "MEDIUMVIOLETRED": Color(199, 21, 133), 252 "MIDNIGHTBLUE": Color(25, 25, 112), 253 "MINTCREAM": Color(245, 255, 250), 254 "MISTYROSE": Color(255, 228, 225), 255 "MOCCASIN": Color(255, 228, 181), 256 "NAVAJOWHITE": Color(255, 222, 173), 257 "NAVY": Color(0, 0, 128), 258 "OLDLACE": Color(253, 245, 230), 259 "OLIVE": Color(128, 128, 0), 260 "OLIVEDRAB": Color(107, 142, 35), 261 "ORANGE": Color(255, 165, 0), 262 "ORANGERED": Color(255, 69, 0), 263 "ORCHID": Color(218, 112, 214), 264 "PALEGOLDENROD": Color(238, 232, 170), 265 "PALEGREEN": Color(152, 251, 152), 266 "PALETURQUOISE": Color(175, 238, 238), 267 "PALEVIOLETRED": Color(219, 112, 147), 268 "PAPAYAWHIP": Color(255, 239, 213), 269 "PEACHPUFF": Color(255, 218, 185), 270 "PERU": Color(205, 133, 63), 271 "PINK": Color(255, 192, 203), 272 "PLUM": Color(221, 160, 221), 273 "POWDERBLUE": Color(176, 224, 230), 274 "PURPLE": Color(128, 0, 128), 275 "RED": Color(255, 0, 0), 276 "ROSYBROWN": Color(188, 143, 143), 277 "ROYALBLUE": Color(65, 105, 225), 278 "SADDLEBROWN": Color(139, 69, 19), 279 "SALMON": Color(250, 128, 114), 280 "SANDYBROWN": Color(244, 164, 96), 281 "SEAGREEN": Color(46, 139, 87), 282 "SEASHELL": Color(255, 245, 238), 283 "SIENNA": Color(160, 82, 45), 284 "SILVER": Color(192, 192, 192), 285 "SKYBLUE": Color(135, 206, 235), 286 "SLATEBLUE": Color(106, 90, 205), 287 "SLATEGRAY": Color(112, 128, 144), 288 "SLATEGREY": Color(112, 128, 144), 289 "SNOW": Color(255, 250, 250), 290 "SPRINGGREEN": Color(0, 255, 127), 291 "STEELBLUE": Color(70, 130, 180), 292 "TAN": Color(210, 180, 140), 293 "TEAL": Color(0, 128, 128), 294 "THISTLE": Color(216, 191, 216), 295 "TOMATO": Color(255, 99, 71), 296 "TURQUOISE": Color(64, 224, 208), 297 "VIOLET": Color(238, 130, 238), 298 "WHEAT": Color(245, 222, 179), 299 "WHITE": Color(255, 255, 255), 300 "WHITESMOKE": Color(245, 245, 245), 301 "YELLOW": Color(255, 255, 0), 302 "YELLOWGREEN": Color(154, 205, 50) 303} 304