NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

mutable.py (9622B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\chroma\mutable.py
      2 from __future__ import division
      3 from __future__ import print_function
      4 import collections
      5 import mathext
      6 from chroma.color import Color
      7 COLORS = {'aqua': (240, 248, 255),
      8  'black': (0, 0, 0),
      9  'blue': (0, 0, 255),
     10  'fuchsia': (255, 0, 255),
     11  'gray': (128, 128, 128),
     12  'green': (0, 128, 0),
     13  'lime': (0, 255, 0),
     14  'maroon': (128, 0, 0),
     15  'navy': (0, 0, 128),
     16  'olive': (128, 128, 0),
     17  'purple': (128, 0, 128),
     18  'red': (255, 0, 0),
     19  'silver': (192, 192, 192),
     20  'teal': (0, 128, 128),
     21  'white': (255, 255, 255),
     22  'yellow': (255, 255, 0)}
     23 
     24 def _get_rgb_by_name(name):
     25     return tuple((x / 255.0 for x in COLORS[name]))
     26 
     27 
     28 class ColorMutable(collections.Sequence):
     29     COMBINED_KWARGS = [('rgb', [('red', 'r'), ('green', 'g'), ('blue', 'b')]), ('rgba', [('red', 'r'),
     30        ('green', 'g'),
     31        ('blue', 'b'),
     32        ('alpha', 'a')]), ('hsl', [('hue', 'h'), ('saturation', 's'), ('lightness', 'l')])]
     33 
     34     def __init__(self, *args, **kwargs):
     35         rgb = _get_rgb_by_name('black')
     36         a = 1.0
     37         if len(args) == 1:
     38             args = args[0]
     39             if isinstance(args, (ColorMutable, Color)):
     40                 args = args.rgba
     41             elif isinstance(args, (str, unicode)):
     42                 if args in COLORS:
     43                     args = _get_rgb_by_name(args.lower())
     44                 else:
     45                     args = hex_to_rgb(args)
     46             elif isinstance(args, collections.Sequence):
     47                 pass
     48             else:
     49                 raise TypeError('ColorMutable value should be a color name, hex value, or a Coloror ColorMutable instance')
     50         if len(args) == 3:
     51             rgb = tuple(args)
     52         elif len(args) == 4:
     53             rgb = tuple(args[:3])
     54             a = args[3]
     55         elif args:
     56             raise ValueError('Invalid number of color components')
     57         self.rgb = rgb
     58         self.a = a
     59         for key, components in self.COMBINED_KWARGS:
     60             changed = False
     61             if key in kwargs:
     62                 value = list(kwargs.pop(key))
     63                 changed = True
     64             else:
     65                 value = list(getattr(self, key))
     66             for i, names in enumerate(components):
     67                 if len([ name for name in names if name in kwargs ]) > 1:
     68                     raise TypeError('Duplicate argument found for {}'.format(names[0]))
     69                 for name in names:
     70                     if name in kwargs:
     71                         value[i] = kwargs.pop(name)
     72                         changed = True
     73 
     74             if changed:
     75                 setattr(self, key, value)
     76 
     77         if 'hex' in kwargs:
     78             self.hex = kwargs.pop('hex')
     79         if kwargs:
     80             raise TypeError("'{}' is an invalid keyword argument for this function".format(kwargs.keys()[0]))
     81 
     82     @property
     83     def red(self):
     84         return self._rgb[0]
     85 
     86     @red.setter
     87     def red(self, red):
     88         if 0.0 > red or red > 1.0:
     89             raise ValueError('Red should be in the range [0, 1]')
     90         self._rgb[0] = red
     91 
     92     r = red
     93 
     94     @property
     95     def green(self):
     96         return self._rgb[1]
     97 
     98     @green.setter
     99     def green(self, green):
    100         if 0.0 > green or green > 1.0:
    101             raise ValueError('Green should be in the range [0, 1]')
    102         self._rgb[1] = green
    103 
    104     g = green
    105 
    106     @property
    107     def blue(self):
    108         return self._rgb[2]
    109 
    110     @blue.setter
    111     def blue(self, blue):
    112         if 0.0 > blue or blue > 1.0:
    113             raise ValueError('Blue should be in the range [0, 1]')
    114         self._rgb[2] = blue
    115 
    116     b = blue
    117 
    118     @property
    119     def alpha(self):
    120         return self._alpha
    121 
    122     @alpha.setter
    123     def alpha(self, alpha):
    124         if 0.0 > alpha or alpha > 1.0:
    125             raise ValueError('Alpha should be in the range [0, 1]')
    126         self._alpha = alpha
    127 
    128     a = alpha
    129 
    130     @property
    131     def rgb(self):
    132         return tuple(self._rgb)
    133 
    134     @rgb.setter
    135     def rgb(self, rgb):
    136         _validate_rgb(rgb)
    137         self._rgb = list(rgb)
    138 
    139     @property
    140     def rgba(self):
    141         r, g, b = self.rgb
    142         return (r,
    143          g,
    144          b,
    145          self.a)
    146 
    147     @rgba.setter
    148     def rgba(self, rgba):
    149         r, g, b, a = rgba
    150         self.rgb = [r, g, b]
    151         self.a = a
    152 
    153     @property
    154     def hsl(self):
    155         return rgb_to_hsl(self.rgb)
    156 
    157     @hsl.setter
    158     def hsl(self, hsl):
    159         self.rgb = hsl_to_rgb(hsl)
    160 
    161     @property
    162     def hue(self):
    163         return rgb_to_hsl(self._rgb)[0]
    164 
    165     @hue.setter
    166     def hue(self, hue):
    167         if 0.0 > hue or hue > 1.0:
    168             raise ValueError('Hue should be in the range [0, 1]')
    169         _, saturation, lightness = self.hsl
    170         self.hsl = (hue, saturation, lightness)
    171 
    172     h = hue
    173 
    174     @property
    175     def saturation(self):
    176         return rgb_to_hsl(self._rgb)[1]
    177 
    178     @saturation.setter
    179     def saturation(self, saturation):
    180         print('set s to', saturation)
    181         if 0.0 > saturation or saturation > 1.0:
    182             raise ValueError('Saturation should be in the range [0, 1]')
    183         hue, _, lightness = self.hsl
    184         self.hsl = (hue, saturation, lightness)
    185 
    186     s = saturation
    187 
    188     @property
    189     def lightness(self):
    190         return rgb_to_hsl(self._rgb)[2]
    191 
    192     @lightness.setter
    193     def lightness(self, lightness):
    194         if 0.0 > lightness or lightness > 1.0:
    195             raise ValueError('Lightness should be in the range [0, 1]')
    196         hue, saturation, _ = self.hsl
    197         self.hsl = (hue, saturation, lightness)
    198 
    199     l = lightness
    200 
    201     @property
    202     def hex(self):
    203         return _rgb_to_hex(self.rgb)
    204 
    205     @hex.setter
    206     def hex(self, hex):
    207         self.rgb = hex_to_rgb(hex)
    208 
    209     @property
    210     def hex_rgba(self):
    211         r, g, b, a = map(lambda x: int(round(x * 255.0)), self.rgba)
    212         return u'#{:02x}{:02x}{:02x}{:02x}'.format(r, g, b, a)
    213 
    214     @property
    215     def hex_argb(self):
    216         r, g, b, a = map(lambda x: int(round(x * 255.0)), self.rgba)
    217         return u'#{:02x}{:02x}{:02x}{:02x}'.format(a, r, g, b)
    218 
    219     def __eq__(self, other):
    220         if isinstance(other, ColorMutable):
    221             return self.hex == other.hex
    222         return NotImplemented
    223 
    224     def __ne__(self, other):
    225         equal = self.__eq__(other)
    226         if equal is NotImplemented:
    227             return equal
    228         return not equal
    229 
    230     def __str__(self):
    231         return self.hex
    232 
    233     def __repr__(self):
    234         return '<chroma.ColorMutable {}>'.format(self.hex)
    235 
    236     def __getitem__(self, item):
    237         return self.rgba[item]
    238 
    239     def __len__(self):
    240         return len(self.rgba)
    241 
    242 
    243 def _validate_rgb(rgb):
    244     r, g, b = rgb
    245     for name, value in {'Red': r,
    246      'Green': g,
    247      'Blue': b}.items():
    248         if value > 1.0 or value < 0.0:
    249             raise ValueError('{name} must be between 0 and 1. You provided {value}.'.format(name=name, value=value))
    250 
    251 
    252 def rgb_to_hsl(rgb):
    253     _validate_rgb(rgb)
    254     r, g, b = [ float(value) for value in rgb ]
    255     value_min = min(r, g, b)
    256     value_max = max(r, g, b)
    257     diff = value_max - value_min
    258     value_sum = value_min + value_max
    259     lightness = value_sum / 2
    260     if mathext.is_close(diff, 0.0, abs_tol=1e-07):
    261         return (0.0, 0.0, lightness)
    262     if lightness < 0.5:
    263         saturation = diff / value_sum
    264     else:
    265         saturation = diff / (2.0 - value_sum)
    266     dr = ((value_max - r) / 6 + diff / 2) / diff
    267     dg = ((value_max - g) / 6 + diff / 2) / diff
    268     db = ((value_max - b) / 6 + diff / 2) / diff
    269     if r == value_max:
    270         hue = db - dg
    271     elif g == value_max:
    272         hue = 0.3333333333333333 + dr - db
    273     elif b == value_max:
    274         hue = 0.6666666666666666 + dg - dr
    275     if hue < 0:
    276         hue += 1
    277     if hue > 1:
    278         hue -= 1
    279     return (hue, saturation, lightness)
    280 
    281 
    282 def hsl_to_rgb(hsl):
    283     h, s, l = [ float(value) for value in hsl ]
    284     for name, value in {'Hue': h,
    285      'Saturation': s,
    286      'Lightness': l}.items():
    287         if value < 0.0 or 1.0 < value:
    288             raise ValueError('{} must be between 0 and 1'.format(name))
    289 
    290     if mathext.is_close(s, 0.0, abs_tol=1e-07):
    291         return (l, l, l)
    292     if l < 0.5:
    293         v2 = l * (1.0 + s)
    294     else:
    295         v2 = l + s - s * l
    296     v1 = 2.0 * l - v2
    297     r = _hue_to_rgb(v1, v2, h + 0.3333333333333333)
    298     g = _hue_to_rgb(v1, v2, h)
    299     b = _hue_to_rgb(v1, v2, h - 0.3333333333333333)
    300     return (r, g, b)
    301 
    302 
    303 def _hue_to_rgb(v1, v2, vH):
    304     while vH < 0:
    305         vH += 1
    306 
    307     while vH > 1:
    308         vH -= 1
    309 
    310     if 6 * vH < 1:
    311         return v1 + (v2 - v1) * 6 * vH
    312     if 2 * vH < 1:
    313         return v2
    314     if 3 * vH < 2:
    315         return v1 + (v2 - v1) * (0.6666666666666666 - vH) * 6
    316     return v1
    317 
    318 
    319 def rgb_to_hex(rgb):
    320     _validate_rgb(rgb)
    321     r, g, b = [ float(value) for value in rgb ]
    322     return _rgb_to_hex((r, g, b))
    323 
    324 
    325 def _rgb_to_hex(rgb):
    326     r, g, b = [ int(round(value * 255)) for value in rgb ]
    327     return '#{:02x}{:02x}{:02x}'.format(r, g, b)
    328 
    329 
    330 def hex_to_rgb(color):
    331     try:
    332         if not isinstance(color, (str, unicode)):
    333             raise ValueError()
    334         hex_value = color
    335         if color.startswith('#'):
    336             hex_value = color[1:]
    337         if len(hex_value) == 6:
    338             r, g, b = hex_value[0:2], hex_value[2:4], hex_value[4:6]
    339         elif len(hex_value) == 3:
    340             r, g, b = hex_value[0] * 2, hex_value[1] * 2, hex_value[2] * 2
    341         else:
    342             raise ValueError()
    343     except Exception:
    344         raise ValueError('Invalid hex color value provided: {!r}'.format(color))
    345 
    346     return tuple([ float(int(x, 16)) / 255 for x in (r, g, b) ])
    347 
    348 
    349 def hex_to_hsl(color):
    350     return rgb_to_hsl(hex_to_rgb(color))
    351 
    352 
    353 def hsl_to_hex(hsl):
    354     return _rgb_to_hex(hsl_to_rgb(hsl))