@@ -35,7 +35,9 @@ class BadColor(Exception):
3535
3636# generic class
3737class ColorDB :
38- def __init__ (self , fp , lineno ):
38+ def __init__ (self , fp ):
39+ lineno = 2
40+ self .__name = fp .name
3941 # Maintain several dictionaries for indexing into the color database.
4042 # Note that while Tk supports RGB intensities of 4, 8, 12, or 16 bits,
4143 # for now we only support 8 bit intensities. At least on OpenWindows,
@@ -54,6 +56,7 @@ def __init__(self, fp, lineno):
5456 if not line :
5557 break
5658 # get this compiled regular expression from derived class
59+ ## print '%3d: %s' % (lineno, line[:-1])
5760 mo = self ._re .match (line )
5861 if not mo :
5962 sys .stderr .write ('Error in %s, line %d\n ' % (fp .name , lineno ))
@@ -62,9 +65,10 @@ def __init__(self, fp, lineno):
6265 #
6366 # extract the red, green, blue, and name
6467 #
65- red , green , blue = map ( int , mo . group ( ' red' , ' green' , ' blue' ) )
66- name = mo . group ( 'name' )
68+ red , green , blue = self . _extractrgb ( mo )
69+ name = self . _extractname ( mo )
6770 keyname = string .lower (name )
71+ ## print keyname, '(%d, %d, %d)' % (red, green, blue)
6872 #
6973 # TBD: for now the `name' is just the first named color with the
7074 # rgb values we find. Later, we might want to make the two word
@@ -81,23 +85,36 @@ def __init__(self, fp, lineno):
8185 self .__byname [keyname ] = key
8286 lineno = lineno + 1
8387
88+ # override in derived classes
89+ def _extractrgb (self , mo ):
90+ return map (int , mo .group ('red' , 'green' , 'blue' ))
91+
92+ def _extractname (self , mo ):
93+ return mo .group ('name' )
94+
95+ def filename (self ):
96+ return self .__name
97+
8498 def find_byrgb (self , rgbtuple ):
99+ """Return name for rgbtuple"""
85100 try :
86101 return self .__byrgb [rgbtuple ]
87102 except KeyError :
88103 raise BadColor (rgbtuple )
89104
90105 def find_byname (self , name ):
106+ """Return (red, green, blue) for name"""
91107 name = string .lower (name )
92108 try :
93109 return self .__byname [name ]
94110 except KeyError :
95111 raise BadColor (name )
96112
97113 def nearest (self , red , green , blue ):
98- # TBD: use Voronoi diagrams, Delaunay triangulation, or octree for
99- # speeding up the locating of nearest point. Exhaustive search is
100- # inefficient, but may be fast enough.
114+ """Return the name of color nearest (red, green, blue)"""
115+ # TBD: should we use Voronoi diagrams, Delaunay triangulation, or
116+ # octree for speeding up the locating of nearest point? Exhaustive
117+ # search is inefficient, but seems fast enough.
101118 nearest = - 1
102119 nearest_name = ''
103120 for name , aliases in self .__byrgb .values ():
@@ -133,38 +150,66 @@ def aliases_of(self, red, green, blue):
133150
134151class RGBColorDB (ColorDB ):
135152 _re = re .compile (
136- '\s*(?P<red>\d+)\s+(?P<green>\d+)\s+(?P<blue>\d+)\s+(?P<name>.*)' )
153+ '\s*(?P<red>\d+)\s+(?P<green>\d+)\s+(?P<blue>\d+)\s+(?P<name>.*)' )
154+
155+
156+ class HTML40DB (ColorDB ):
157+ _re = re .compile ('(?P<name>\S+)\s+(?P<hexrgb>#[0-9a-fA-F]{6})' )
158+
159+ def _extractrgb (self , mo ):
160+ return rrggbb_to_triplet (mo .group ('hexrgb' ))
161+
162+ class LightlinkDB (HTML40DB ):
163+ _re = re .compile ('(?P<name>(.+))\s+(?P<hexrgb>#[0-9a-fA-F]{6})' )
164+
165+ def _extractname (self , mo ):
166+ return string .strip (mo .group ('name' ))
167+
168+ class WebsafeDB (ColorDB ):
169+ _re = re .compile ('(?P<hexrgb>#[0-9a-fA-F]{6})' )
170+
171+ def _extractrgb (self , mo ):
172+ return rrggbb_to_triplet (mo .group ('hexrgb' ))
173+
174+ def _extractname (self , mo ):
175+ return string .upper (mo .group ('hexrgb' ))
137176
138177
139178
140179# format is a tuple (RE, SCANLINES, CLASS) where RE is a compiled regular
141180# expression, SCANLINES is the number of header lines to scan, and CLASS is
142181# the class to instantiate if a match is found
143182
144- X_RGB_TXT = re .compile ('XConsortium' ), 1 , RGBColorDB
183+ FILETYPES = [
184+ (re .compile ('XConsortium' ), RGBColorDB ),
185+ (re .compile ('HTML' ), HTML40DB ),
186+ (re .compile ('lightlink' ), LightlinkDB ),
187+ (re .compile ('Websafe' ), WebsafeDB ),
188+ ]
145189
146- def get_colordb (file , filetype = X_RGB_TXT ):
190+ def get_colordb (file , filetype = None ):
147191 colordb = None
148- fp = None
149- typere , scanlines , class_ = filetype
192+ fp = open (file )
150193 try :
151- try :
152- lineno = 0
153- fp = open (file )
154- while lineno < scanlines :
155- line = fp .readline ()
156- if not line :
157- break
158- mo = typere .search (line )
159- if mo :
160- colordb = class_ (fp , lineno )
161- break
162- lineno = lineno + 1
163- except IOError :
164- pass
194+ line = fp .readline ()
195+ if not line :
196+ return None
197+ # try to determine the type of RGB file it is
198+ if filetype is None :
199+ filetypes = FILETYPES
200+ else :
201+ filetypes = [filetype ]
202+ for typere , class_ in filetypes :
203+ mo = typere .search (line )
204+ if mo :
205+ break
206+ else :
207+ # no matching type
208+ return None
209+ # we know the type and the class to grok the type, so suck it in
210+ colordb = class_ (fp )
165211 finally :
166- if fp :
167- fp .close ()
212+ fp .close ()
168213 # save a global copy
169214 global DEFAULT_DB
170215 DEFAULT_DB = colordb
@@ -175,6 +220,7 @@ def get_colordb(file, filetype=X_RGB_TXT):
175220_namedict = {}
176221def rrggbb_to_triplet (color , atoi = string .atoi ):
177222 """Converts a #rrggbb color to the tuple (red, green, blue)."""
223+ global _namedict
178224 rgbtuple = _namedict .get (color )
179225 if rgbtuple is None :
180226 if color [0 ] <> '#' :
@@ -190,6 +236,7 @@ def rrggbb_to_triplet(color, atoi=string.atoi):
190236_tripdict = {}
191237def triplet_to_rrggbb (rgbtuple ):
192238 """Converts a (red, green, blue) tuple to #rrggbb."""
239+ global _tripdict
193240 hexname = _tripdict .get (rgbtuple )
194241 if hexname is None :
195242 hexname = '#%02x%02x%02x' % rgbtuple
0 commit comments