Module colors
[hide private]
[frames] | no frames]

Source Code for Module colors

  1  #colors.py 
  2  #A part of NonVisual Desktop Access (NVDA) 
  3  #Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/> 
  4  #This file is covered by the GNU General Public License. 
  5  #See the file COPYING for more details. 
  6   
  7  from collections import namedtuple 
  8  import math 
  9  from ctypes.wintypes import COLORREF 
 10  import re 
11 12 -class RGB(namedtuple('RGB',('red','green','blue'))):
13 """Represents a color as an RGB (red green blue) value""" 14 15 @classmethod
16 - def fromCOLORREF(cls,c):
17 """factory method to create an RGB from a COLORREF ctypes instance""" 18 if isinstance(c,COLORREF): 19 c=c.value 20 return cls(c&0xff,(c>>8)&0xff,(c>>16)&0xff)
21 22 _re_RGBFunctionString=re.compile(r'rgb\(\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d+%?)\s*\)',re.I) 23 _re_RGBAFunctionString=re.compile(r'rgba\(\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*\d+(\.\d+)?\s*\)',re.I) 24 25 @staticmethod
26 - def _RGBStringValToInt(s):
27 val=int(round(int(s[:-1])*2.55)) if s.endswith('%') else int(s) 28 if val<0 or val>255: 29 raise ValueError("%s out of range"%val) 30 return val
31 32 @classmethod
33 - def fromString(cls,s):
34 """ 35 Factory method to create an RGB instance from a css RGB string representation. 36 """ 37 s=s.strip() 38 #Try to match on the form RGB(x,y,z) 39 m=cls._re_RGBFunctionString.match(s) or cls._re_RGBAFunctionString.match(s) 40 if m: 41 r=cls._RGBStringValToInt(m.group(1)) 42 g=cls._RGBStringValToInt(m.group(2)) 43 b=cls._RGBStringValToInt(m.group(3)) 44 return RGB(r,g,b) 45 if s.startswith('#'): 46 sLen=len(s) 47 try: 48 val=int(s[1:],16) 49 except ValueError: 50 val=None 51 if val is not None: 52 #Perhaps its a #aarrggbb or #rrggbb hex string 53 if sLen==7 or sLen==9: 54 r=(val>>16)&0xff 55 g=(val>>8)&0xff 56 b=val&0xff 57 return RGB(r,g,b) 58 #Perhaps its a #argb or #rgb hex string 59 if sLen==4 or sLen==5: 60 r=((val>>8)&0xf)+(((val>>8)&0xf)<<4) 61 g=((val>>4)&0xf)+(((val>>4)&0xf)<<4) 62 b=(val&0xf)+((val&0xf)<<4) 63 return RGB(r,g,b) 64 raise ValueError("invalid RGB string: %s"%s)
65 66 @property
67 - def name(self):
68 foundName=RGBToNames.get(self,None) 69 if foundName: 70 return foundName 71 foundName=RGBToNamesCache.get(self,None) 72 if foundName: 73 return foundName 74 longestDistance=255.0 75 closestName=_("unknown color") 76 for possibleRGB,possibleName in RGBToNames.iteritems(): 77 distance=math.sqrt(abs(self.red-possibleRGB.red)**2+abs(self.green-possibleRGB.green)**2+abs(self.blue-possibleRGB.blue)**2) 78 if distance<longestDistance: 79 longestDistance=distance 80 closestName=possibleName 81 RGBToNamesCache[self]=closestName 82 return closestName
83 84 RGBToNamesCache={} 85 86 RGBToNames={ 87 #Standard 16 HTML 4 colors 88 RGB(0x00,0x00,0x00):_('black'), 89 RGB(0x00,0x80,0x00):_('green'), 90 RGB(0xc0,0xc0,0xc0):_('light grey'), 91 RGB(0x00,0xff,0x00):_('lime'), 92 RGB(0x80,0x80,0x80):_('grey'), 93 RGB(0x80,0x80,0x00):_('olive'), 94 RGB(0xff,0xff,0xff):_('white'), 95 RGB(0xff,0xff,0x00):_('yellow'), 96 RGB(0x80,0x00,0x00):_('dark red'), 97 RGB(0x00,0x00,0xa0):_('navy blue'), 98 RGB(0xff,0x00,0x00):_('red'), 99 RGB(0x00,0x00,0xff):_('blue'), 100 RGB(0x80,0x00,0x80):_('purple'), 101 RGB(0x00,0x80,0x80):_('teal'), 102 RGB(0xff,0x00,0xff):_('fuchsia'), 103 RGB(0x00,0xff,0xff):_('aqua'), 104 #Extra CSS 2.1 color 105 RGB(0xff,0xa5,0x00):_('orange'), 106 } 107