from comInterfaces.tom import ITextDocument\r
import tones\r
import textInfos.offsets\r
+import colors\r
import time\r
import displayModel\r
import IAccessibleHandler\r
import oleacc\r
-import re\r
-import colors\r
import JABHandler\r
import winUser\r
import globalVars\r
except:\r
return ""\r
\r
- re_IA2RGB=re.compile(r'rgb\((\d+),\s(\d+),\s(\d+)\)')\r
-\r
def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):\r
try:\r
startOffset,endOffset,attribsString=self.obj.IAccessibleTextObject.attributes(offset)\r
formatField["invalid-spelling"]=True\r
color=formatField.get('color')\r
if color:\r
- m=self.re_IA2RGB.match(color)\r
- if m:\r
- formatField['color']=colors.RGB(int(m.group(1)),int(m.group(2)),int(m.group(3)))\r
+ try:\r
+ formatField['color']=colors.RGB.fromString(color)\r
+ except ValueError:\r
+ pass\r
backgroundColor=formatField.get('background-color')\r
if backgroundColor:\r
- m=self.re_IA2RGB.match(backgroundColor)\r
- if m:\r
- formatField['background-color']=colors.RGB(int(m.group(1)),int(m.group(2)),int(m.group(3)))\r
+ try:\r
+ formatField['background-color']=colors.RGB.fromString(backgroundColor)\r
+ except ValueError:\r
+ pass\r
return formatField,(startOffset,endOffset)\r
\r
def _getCharacterOffsets(self,offset):\r
colNum+=((ord(ch.upper())-ord('A')+1)*(26**index))\r
return rowNum,colNum\r
\r
-def symphonyColorToRGB(symphonyColor):\r
- h=symphonyColor[-6:]\r
- return colors.RGB(int(h[0:2],16),int(h[2:4],16),int(h[4:6],16))\r
-\r
class JAB_OOTable(JAB):\r
\r
def _get_rowCount(self):\r
except KeyError:\r
color=None\r
if color:\r
- formatField['color']=symphonyColorToRGB(color)\r
+ formatField['color']=colors.RGB.fromString(color) \r
try:\r
backgroundColor=formatField.pop('CharBackColor')\r
except KeyError:\r
backgroundColor=None\r
if backgroundColor:\r
- formatField['background-color']=symphonyColorToRGB(backgroundColor)\r
+ formatField['background-color']=colors.RGB.fromString(backgroundColor)\r
\r
# optimisation: Assume a hyperlink occupies a full attribute run.\r
try:\r
\r
from collections import namedtuple\r
import math\r
+from ctypes.wintypes import COLORREF\r
+import re\r
\r
-RGB=namedtuple('RGB',('red','green','blue'))\r
+class RGB(namedtuple('RGB',('red','green','blue'))):\r
+ """Represents a color as an RGB (red green blue) value"""\r
+\r
+ @classmethod\r
+ def fromCOLORREF(cls,c):\r
+ """factory method to create an RGB from a COLORREF ctypes instance"""\r
+ if not isinstance(c,COLORREF): raise ValueError("%s is not a COLORREF instance"%c)\r
+ return cls(c.value&0xff,(c.value<<8)&0xff,(c.value<<16)&0xff)\r
+\r
+ _re_RGBFunctionString=re.compile(r'rgb\(\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d+%?)\s*\)',re.I)\r
+ _re_RGBAFunctionString=re.compile(r'rgba\(\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*\d+(\.\d+)?\s*\)',re.I)\r
+\r
+ @staticmethod\r
+ def _RGBStringValToInt(s):\r
+ val=int(round(int(s[:-1])*2.55)) if s.endswith('%') else int(s)\r
+ if val<0 or val>255:\r
+ raise ValueError("%s out of range"%val)\r
+ return val\r
+\r
+ @classmethod\r
+ def fromString(cls,s):\r
+ """\r
+ Factory method to create an RGB instance from a css RGB string representation.\r
+ """\r
+ s=s.strip()\r
+ #Try to match on the form RGB(x,y,z)\r
+ m=cls._re_RGBFunctionString.match(s) or cls._re_RGBAFunctionString.match(s)\r
+ if m:\r
+ r=cls._RGBStringValToInt(m.group(1))\r
+ g=cls._RGBStringValToInt(m.group(2))\r
+ b=cls._RGBStringValToInt(m.group(3))\r
+ return RGB(r,g,b)\r
+ if s.startswith('#'):\r
+ sLen=len(s)\r
+ try:\r
+ val=int(s[1:],16)\r
+ except ValueError:\r
+ val=None\r
+ if val is not None:\r
+ #Perhaps its a #aarrggbb or #rrggbb hex string\r
+ if sLen==7 or sLen==9:\r
+ r=(val>>16)&0xff\r
+ g=(val>>8)&0xff\r
+ b=val&0xff\r
+ return RGB(r,g,b)\r
+ #Perhaps its a #argb or #rgb hex string\r
+ if sLen==4 or sLen==5:\r
+ r=((val>>8)&0xf)+(((val>>8)&0xf)<<4)\r
+ g=((val>>4)&0xf)+(((val>>4)&0xf)<<4)\r
+ b=(val&0xf)+((val&0xf)<<4)\r
+ return RGB(r,g,b)\r
+ raise ValueError("invalid RGB string: %s"%s)\r
+\r
+ @property\r
+ def name(self):\r
+ foundName=RGBToNames.get(self,None)\r
+ if not foundName:\r
+ closestRGB=sorted(RGBToNames.iterkeys(),key=lambda x: math.sqrt((abs(self.red-x.red)*0.3)**2+(abs(self.green-x.green)*0.59)**2+(abs(self.blue-x.blue)*0.11)**2))[0]\r
+ foundName=RGBToNames[closestRGB]\r
+ RGBToNames[self]=foundName\r
+ return foundName\r
\r
RGBToNames={\r
#Standard 16 HTML 4 colors\r
RGB(0xff,0xa5,0x00):_('orange'),\r
}\r
\r
-def findColorName(rgb):\r
- foundName=RGBToNames.get(rgb,None)\r
- if not foundName:\r
- closestRGB=sorted(RGBToNames.iterkeys(),key=lambda x: math.sqrt((abs(rgb.red-x.red)*0.3)**2+(abs(rgb.green-x.green)*0.59)**2+(abs(rgb.blue-x.blue)*0.11)**2))[0]\r
- foundName=RGBToNames[closestRGB]\r
- RGBToNames[rgb]=foundName\r
- return foundName\r
-\r
-\r
color=attrs.get("color")\r
oldColor=attrsCache.get("color") if attrsCache is not None else None\r
if color and color!=oldColor:\r
- textList.append(colors.findColorName(color))\r
+ textList.append(color.name if isinstance(color,colors.RGB) else unicode(color))\r
backgroundColor=attrs.get("background-color")\r
oldBackgroundColor=attrsCache.get("background-color") if attrsCache is not None else None\r
if backgroundColor and backgroundColor!=oldBackgroundColor:\r
- textList.append(_("on {backgroundColor}").format(backgroundColor=colors.findColorName(backgroundColor)))\r
+ textList.append(_("on {backgroundColor}").format(backgroundColor=backgroundColor.name if isinstance(backgroundColor,colors.RGB) else unicode(backgroundColor)))\r
if formatConfig["reportLineNumber"]:\r
lineNumber=attrs.get("line-number")\r
oldLineNumber=attrsCache.get("line-number") if attrsCache is not None else None\r