| 1 | /*** |
| 2 | |
| 3 | MochiKit.Color 1.4 |
| 4 | |
| 5 | See <http://mochikit.com/> for documentation, downloads, license, etc. |
| 6 | |
| 7 | (c) 2005 Bob Ippolito and others. All rights Reserved. |
| 8 | |
| 9 | ***/ |
| 10 | |
| 11 | if (typeof(dojo) != 'undefined') { |
| 12 | dojo.provide('MochiKit.Color'); |
| 13 | dojo.require('MochiKit.Base'); |
| 14 | dojo.require('MochiKit.DOM'); |
| 15 | dojo.require('MochiKit.Style'); |
| 16 | } |
| 17 | |
| 18 | if (typeof(JSAN) != 'undefined') { |
| 19 | JSAN.use("MochiKit.Base", []); |
| 20 | JSAN.use("MochiKit.DOM", []); |
| 21 | JSAN.use("MochiKit.Style", []); |
| 22 | } |
| 23 | |
| 24 | try { |
| 25 | if (typeof(MochiKit.Base) == 'undefined') { |
| 26 | throw ""; |
| 27 | } |
| 28 | } catch (e) { |
| 29 | throw "MochiKit.Color depends on MochiKit.Base"; |
| 30 | } |
| 31 | |
| 32 | try { |
| 33 | if (typeof(MochiKit.DOM) == 'undefined') { |
| 34 | throw ""; |
| 35 | } |
| 36 | } catch (e) { |
| 37 | throw "MochiKit.Color depends on MochiKit.DOM"; |
| 38 | } |
| 39 | |
| 40 | try { |
| 41 | if (typeof(MochiKit.Style) == 'undefined') { |
| 42 | throw ""; |
| 43 | } |
| 44 | } catch (e) { |
| 45 | throw "MochiKit.Color depends on MochiKit.Style"; |
| 46 | } |
| 47 | |
| 48 | if (typeof(MochiKit.Color) == "undefined") { |
| 49 | MochiKit.Color = {}; |
| 50 | } |
| 51 | |
| 52 | MochiKit.Color.NAME = "MochiKit.Color"; |
| 53 | MochiKit.Color.VERSION = "1.4"; |
| 54 | |
| 55 | MochiKit.Color.__repr__ = function () { |
| 56 | return "[" + this.NAME + " " + this.VERSION + "]"; |
| 57 | }; |
| 58 | |
| 59 | MochiKit.Color.toString = function () { |
| 60 | return this.__repr__(); |
| 61 | }; |
| 62 | |
| 63 | |
| 64 | /** @id MochiKit.Color.Color */ |
| 65 | MochiKit.Color.Color = function (red, green, blue, alpha) { |
| 66 | if (typeof(alpha) == 'undefined' || alpha === null) { |
| 67 | alpha = 1.0; |
| 68 | } |
| 69 | this.rgb = { |
| 70 | r: red, |
| 71 | g: green, |
| 72 | b: blue, |
| 73 | a: alpha |
| 74 | }; |
| 75 | }; |
| 76 | |
| 77 | |
| 78 | // Prototype methods |
| 79 | |
| 80 | MochiKit.Color.Color.prototype = { |
| 81 | |
| 82 | __class__: MochiKit.Color.Color, |
| 83 | |
| 84 | /** @id MochiKit.Color.Color.prototype.colorWithAlpha */ |
| 85 | colorWithAlpha: function (alpha) { |
| 86 | var rgb = this.rgb; |
| 87 | var m = MochiKit.Color; |
| 88 | return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha); |
| 89 | }, |
| 90 | |
| 91 | /** @id MochiKit.Color.Color.prototype.colorWithHue */ |
| 92 | colorWithHue: function (hue) { |
| 93 | // get an HSL model, and set the new hue... |
| 94 | var hsl = this.asHSL(); |
| 95 | hsl.h = hue; |
| 96 | var m = MochiKit.Color; |
| 97 | // convert back to RGB... |
| 98 | return m.Color.fromHSL(hsl); |
| 99 | }, |
| 100 | |
| 101 | /** @id MochiKit.Color.Color.prototype.colorWithSaturation */ |
| 102 | colorWithSaturation: function (saturation) { |
| 103 | // get an HSL model, and set the new hue... |
| 104 | var hsl = this.asHSL(); |
| 105 | hsl.s = saturation; |
| 106 | var m = MochiKit.Color; |
| 107 | // convert back to RGB... |
| 108 | return m.Color.fromHSL(hsl); |
| 109 | }, |
| 110 | |
| 111 | /** @id MochiKit.Color.Color.prototype.colorWithLightness */ |
| 112 | colorWithLightness: function (lightness) { |
| 113 | // get an HSL model, and set the new hue... |
| 114 | var hsl = this.asHSL(); |
| 115 | hsl.l = lightness; |
| 116 | var m = MochiKit.Color; |
| 117 | // convert back to RGB... |
| 118 | return m.Color.fromHSL(hsl); |
| 119 | }, |
| 120 | |
| 121 | /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */ |
| 122 | darkerColorWithLevel: function (level) { |
| 123 | var hsl = this.asHSL(); |
| 124 | hsl.l = Math.max(hsl.l - level, 0); |
| 125 | var m = MochiKit.Color; |
| 126 | return m.Color.fromHSL(hsl); |
| 127 | }, |
| 128 | |
| 129 | /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */ |
| 130 | lighterColorWithLevel: function (level) { |
| 131 | var hsl = this.asHSL(); |
| 132 | hsl.l = Math.min(hsl.l + level, 1); |
| 133 | var m = MochiKit.Color; |
| 134 | return m.Color.fromHSL(hsl); |
| 135 | }, |
| 136 | |
| 137 | /** @id MochiKit.Color.Color.prototype.blendedColor */ |
| 138 | blendedColor: function (other, /* optional */ fraction) { |
| 139 | if (typeof(fraction) == 'undefined' || fraction === null) { |
| 140 | fraction = 0.5; |
| 141 | } |
| 142 | var sf = 1.0 - fraction; |
| 143 | var s = this.rgb; |
| 144 | var d = other.rgb; |
| 145 | var df = fraction; |
| 146 | return MochiKit.Color.Color.fromRGB( |
| 147 | (s.r * sf) + (d.r * df), |
| 148 | (s.g * sf) + (d.g * df), |
| 149 | (s.b * sf) + (d.b * df), |
| 150 | (s.a * sf) + (d.a * df) |
| 151 | ); |
| 152 | }, |
| 153 | |
| 154 | /** @id MochiKit.Color.Color.prototype.compareRGB */ |
| 155 | compareRGB: function (other) { |
| 156 | var a = this.asRGB(); |
| 157 | var b = other.asRGB(); |
| 158 | return MochiKit.Base.compare( |
| 159 | [a.r, a.g, a.b, a.a], |
| 160 | [b.r, b.g, b.b, b.a] |
| 161 | ); |
| 162 | }, |
| 163 | |
| 164 | /** @id MochiKit.Color.Color.prototype.isLight */ |
| 165 | isLight: function () { |
| 166 | return this.asHSL().b > 0.5; |
| 167 | }, |
| 168 | |
| 169 | /** @id MochiKit.Color.Color.prototype.isDark */ |
| 170 | isDark: function () { |
| 171 | return (!this.isLight()); |
| 172 | }, |
| 173 | |
| 174 | /** @id MochiKit.Color.Color.prototype.toHSLString */ |
| 175 | toHSLString: function () { |
| 176 | var c = this.asHSL(); |
| 177 | var ccc = MochiKit.Color.clampColorComponent; |
| 178 | var rval = this._hslString; |
| 179 | if (!rval) { |
| 180 | var mid = ( |
| 181 | ccc(c.h, 360).toFixed(0) |
| 182 | + "," + ccc(c.s, 100).toPrecision(4) + "%" |
| 183 | + "," + ccc(c.l, 100).toPrecision(4) + "%" |
| 184 | ); |
| 185 | var a = c.a; |
| 186 | if (a >= 1) { |
| 187 | a = 1; |
| 188 | rval = "hsl(" + mid + ")"; |
| 189 | } else { |
| 190 | if (a <= 0) { |
| 191 | a = 0; |
| 192 | } |
| 193 | rval = "hsla(" + mid + "," + a + ")"; |
| 194 | } |
| 195 | this._hslString = rval; |
| 196 | } |
| 197 | return rval; |
| 198 | }, |
| 199 | |
| 200 | /** @id MochiKit.Color.Color.prototype.toRGBString */ |
| 201 | toRGBString: function () { |
| 202 | var c = this.rgb; |
| 203 | var ccc = MochiKit.Color.clampColorComponent; |
| 204 | var rval = this._rgbString; |
| 205 | if (!rval) { |
| 206 | var mid = ( |
| 207 | ccc(c.r, 255).toFixed(0) |
| 208 | + "," + ccc(c.g, 255).toFixed(0) |
| 209 | + "," + ccc(c.b, 255).toFixed(0) |
| 210 | ); |
| 211 | if (c.a != 1) { |
| 212 | rval = "rgba(" + mid + "," + c.a + ")"; |
| 213 | } else { |
| 214 | rval = "rgb(" + mid + ")"; |
| 215 | } |
| 216 | this._rgbString = rval; |
| 217 | } |
| 218 | return rval; |
| 219 | }, |
| 220 | |
| 221 | /** @id MochiKit.Color.Color.prototype.asRGB */ |
| 222 | asRGB: function () { |
| 223 | return MochiKit.Base.clone(this.rgb); |
| 224 | }, |
| 225 | |
| 226 | /** @id MochiKit.Color.Color.prototype.toHexString */ |
| 227 | toHexString: function () { |
| 228 | var m = MochiKit.Color; |
| 229 | var c = this.rgb; |
| 230 | var ccc = MochiKit.Color.clampColorComponent; |
| 231 | var rval = this._hexString; |
| 232 | if (!rval) { |
| 233 | rval = ("#" + |
| 234 | m.toColorPart(ccc(c.r, 255)) + |
| 235 | m.toColorPart(ccc(c.g, 255)) + |
| 236 | m.toColorPart(ccc(c.b, 255)) |
| 237 | ); |
| 238 | this._hexString = rval; |
| 239 | } |
| 240 | return rval; |
| 241 | }, |
| 242 | |
| 243 | /** @id MochiKit.Color.Color.prototype.asHSV */ |
| 244 | asHSV: function () { |
| 245 | var hsv = this.hsv; |
| 246 | var c = this.rgb; |
| 247 | if (typeof(hsv) == 'undefined' || hsv === null) { |
| 248 | hsv = MochiKit.Color.rgbToHSV(this.rgb); |
| 249 | this.hsv = hsv; |
| 250 | } |
| 251 | return MochiKit.Base.clone(hsv); |
| 252 | }, |
| 253 | |
| 254 | /** @id MochiKit.Color.Color.prototype.asHSL */ |
| 255 | asHSL: function () { |
| 256 | var hsl = this.hsl; |
| 257 | var c = this.rgb; |
| 258 | if (typeof(hsl) == 'undefined' || hsl === null) { |
| 259 | hsl = MochiKit.Color.rgbToHSL(this.rgb); |
| 260 | this.hsl = hsl; |
| 261 | } |
| 262 | return MochiKit.Base.clone(hsl); |
| 263 | }, |
| 264 | |
| 265 | /** @id MochiKit.Color.Color.prototype.toString */ |
| 266 | toString: function () { |
| 267 | return this.toRGBString(); |
| 268 | }, |
| 269 | |
| 270 | /** @id MochiKit.Color.Color.prototype.repr */ |
| 271 | repr: function () { |
| 272 | var c = this.rgb; |
| 273 | var col = [c.r, c.g, c.b, c.a]; |
| 274 | return this.__class__.NAME + "(" + col.join(", ") + ")"; |
| 275 | } |
| 276 | |
| 277 | }; |
| 278 | |
| 279 | // Constructor methods |
| 280 | |
| 281 | MochiKit.Base.update(MochiKit.Color.Color, { |
| 282 | /** @id MochiKit.Color.Color.fromRGB */ |
| 283 | fromRGB: function (red, green, blue, alpha) { |
| 284 | // designated initializer |
| 285 | var Color = MochiKit.Color.Color; |
| 286 | if (arguments.length == 1) { |
| 287 | var rgb = red; |
| 288 | red = rgb.r; |
| 289 | green = rgb.g; |
| 290 | blue = rgb.b; |
| 291 | if (typeof(rgb.a) == 'undefined') { |
| 292 | alpha = undefined; |
| 293 | } else { |
| 294 | alpha = rgb.a; |
| 295 | } |
| 296 | } |
| 297 | return new Color(red, green, blue, alpha); |
| 298 | }, |
| 299 | |
| 300 | /** @id MochiKit.Color.Color.fromHSL */ |
| 301 | fromHSL: function (hue, saturation, lightness, alpha) { |
| 302 | var m = MochiKit.Color; |
| 303 | return m.Color.fromRGB(m.hslToRGB.apply(m, arguments)); |
| 304 | }, |
| 305 | |
| 306 | /** @id MochiKit.Color.Color.fromHSV */ |
| 307 | fromHSV: function (hue, saturation, value, alpha) { |
| 308 | var m = MochiKit.Color; |
| 309 | return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments)); |
| 310 | }, |
| 311 | |
| 312 | /** @id MochiKit.Color.Color.fromName */ |
| 313 | fromName: function (name) { |
| 314 | var Color = MochiKit.Color.Color; |
| 315 | // Opera 9 seems to "quote" named colors(?!) |
| 316 | if (name.charAt(0) == '"') { |
| 317 | name = name.substr(1, name.length - 2); |
| 318 | } |
| 319 | var htmlColor = Color._namedColors[name.toLowerCase()]; |
| 320 | if (typeof(htmlColor) == 'string') { |
| 321 | return Color.fromHexString(htmlColor); |
| 322 | } else if (name == "transparent") { |
| 323 | return Color.transparentColor(); |
| 324 | } |
| 325 | return null; |
| 326 | }, |
| 327 | |
| 328 | /** @id MochiKit.Color.Color.fromString */ |
| 329 | fromString: function (colorString) { |
| 330 | var self = MochiKit.Color.Color; |
| 331 | var three = colorString.substr(0, 3); |
| 332 | if (three == "rgb") { |
| 333 | return self.fromRGBString(colorString); |
| 334 | } else if (three == "hsl") { |
| 335 | return self.fromHSLString(colorString); |
| 336 | } else if (colorString.charAt(0) == "#") { |
| 337 | return self.fromHexString(colorString); |
| 338 | } |
| 339 | return self.fromName(colorString); |
| 340 | }, |
| 341 | |
| 342 | |
| 343 | /** @id MochiKit.Color.Color.fromHexString */ |
| 344 | fromHexString: function (hexCode) { |
| 345 | if (hexCode.charAt(0) == '#') { |
| 346 | hexCode = hexCode.substring(1); |
| 347 | } |
| 348 | var components = []; |
| 349 | var i, hex; |
| 350 | if (hexCode.length == 3) { |
| 351 | for (i = 0; i < 3; i++) { |
| 352 | hex = hexCode.substr(i, 1); |
| 353 | components.push(parseInt(hex + hex, 16) / 255.0); |
| 354 | } |
| 355 | } else { |
| 356 | for (i = 0; i < 6; i += 2) { |
| 357 | hex = hexCode.substr(i, 2); |
| 358 | components.push(parseInt(hex, 16) / 255.0); |
| 359 | } |
| 360 | } |
| 361 | var Color = MochiKit.Color.Color; |
| 362 | return Color.fromRGB.apply(Color, components); |
| 363 | }, |
| 364 | |
| 365 | |
| 366 | _fromColorString: function (pre, method, scales, colorCode) { |
| 367 | // parses either HSL or RGB |
| 368 | if (colorCode.indexOf(pre) === 0) { |
| 369 | colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1); |
| 370 | } |
| 371 | var colorChunks = colorCode.split(/\s*,\s*/); |
| 372 | var colorFloats = []; |
| 373 | for (var i = 0; i < colorChunks.length; i++) { |
| 374 | var c = colorChunks[i]; |
| 375 | var val; |
| 376 | var three = c.substring(c.length - 3); |
| 377 | if (c.charAt(c.length - 1) == '%') { |
| 378 | val = 0.01 * parseFloat(c.substring(0, c.length - 1)); |
| 379 | } else if (three == "deg") { |
| 380 | val = parseFloat(c) / 360.0; |
| 381 | } else if (three == "rad") { |
| 382 | val = parseFloat(c) / (Math.PI * 2); |
| 383 | } else { |
| 384 | val = scales[i] * parseFloat(c); |
| 385 | } |
| 386 | colorFloats.push(val); |
| 387 | } |
| 388 | return this[method].apply(this, colorFloats); |
| 389 | }, |
| 390 | |
| 391 | /** @id MochiKit.Color.Color.fromComputedStyle */ |
| 392 | fromComputedStyle: function (elem, style) { |
| 393 | var d = MochiKit.DOM; |
| 394 | var cls = MochiKit.Color.Color; |
| 395 | for (elem = d.getElement(elem); elem; elem = elem.parentNode) { |
| 396 | var actualColor = MochiKit.Style.getStyle.apply(d, arguments); |
| 397 | if (!actualColor) { |
| 398 | continue; |
| 399 | } |
| 400 | var color = cls.fromString(actualColor); |
| 401 | if (!color) { |
| 402 | break; |
| 403 | } |
| 404 | if (color.asRGB().a > 0) { |
| 405 | return color; |
| 406 | } |
| 407 | } |
| 408 | return null; |
| 409 | }, |
| 410 | |
| 411 | /** @id MochiKit.Color.Color.fromBackground */ |
| 412 | fromBackground: function (elem) { |
| 413 | var cls = MochiKit.Color.Color; |
| 414 | return cls.fromComputedStyle( |
| 415 | elem, "backgroundColor", "background-color") || cls.whiteColor(); |
| 416 | }, |
| 417 | |
| 418 | /** @id MochiKit.Color.Color.fromText */ |
| 419 | fromText: function (elem) { |
| 420 | var cls = MochiKit.Color.Color; |
| 421 | return cls.fromComputedStyle( |
| 422 | elem, "color", "color") || cls.blackColor(); |
| 423 | }, |
| 424 | |
| 425 | /** @id MochiKit.Color.Color.namedColors */ |
| 426 | namedColors: function () { |
| 427 | return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); |
| 428 | } |
| 429 | }); |
| 430 | |
| 431 | |
| 432 | // Module level functions |
| 433 | |
| 434 | MochiKit.Base.update(MochiKit.Color, { |
| 435 | /** @id MochiKit.Color.clampColorComponent */ |
| 436 | clampColorComponent: function (v, scale) { |
| 437 | v *= scale; |
| 438 | if (v < 0) { |
| 439 | return 0; |
| 440 | } else if (v > scale) { |
| 441 | return scale; |
| 442 | } else { |
| 443 | return v; |
| 444 | } |
| 445 | }, |
| 446 | |
| 447 | _hslValue: function (n1, n2, hue) { |
| 448 | if (hue > 6.0) { |
| 449 | hue -= 6.0; |
| 450 | } else if (hue < 0.0) { |
| 451 | hue += 6.0; |
| 452 | } |
| 453 | var val; |
| 454 | if (hue < 1.0) { |
| 455 | val = n1 + (n2 - n1) * hue; |
| 456 | } else if (hue < 3.0) { |
| 457 | val = n2; |
| 458 | } else if (hue < 4.0) { |
| 459 | val = n1 + (n2 - n1) * (4.0 - hue); |
| 460 | } else { |
| 461 | val = n1; |
| 462 | } |
| 463 | return val; |
| 464 | }, |
| 465 | |
| 466 | /** @id MochiKit.Color.hsvToRGB */ |
| 467 | hsvToRGB: function (hue, saturation, value, alpha) { |
| 468 | if (arguments.length == 1) { |
| 469 | var hsv = hue; |
| 470 | hue = hsv.h; |
| 471 | saturation = hsv.s; |
| 472 | value = hsv.v; |
| 473 | alpha = hsv.a; |
| 474 | } |
| 475 | var red; |
| 476 | var green; |
| 477 | var blue; |
| 478 | if (saturation === 0) { |
| 479 | red = value; |
| 480 | green = value; |
| 481 | blue = value; |
| 482 | } else { |
| 483 | var i = Math.floor(hue * 6); |
| 484 | var f = (hue * 6) - i; |
| 485 | var p = value * (1 - saturation); |
| 486 | var q = value * (1 - (saturation * f)); |
| 487 | var t = value * (1 - (saturation * (1 - f))); |
| 488 | switch (i) { |
| 489 | case 1: red = q; green = value; blue = p; break; |
| 490 | case 2: red = p; green = value; blue = t; break; |
| 491 | case 3: red = p; green = q; blue = value; break; |
| 492 | case 4: red = t; green = p; blue = value; break; |
| 493 | case 5: red = value; green = p; blue = q; break; |
| 494 | case 6: // fall through |
| 495 | case 0: red = value; green = t; blue = p; break; |
| 496 | } |
| 497 | } |
| 498 | return { |
| 499 | r: red, |
| 500 | g: green, |
| 501 | b: blue, |
| 502 | a: alpha |
| 503 | }; |
| 504 | }, |
| 505 | |
| 506 | /** @id MochiKit.Color.hslToRGB */ |
| 507 | hslToRGB: function (hue, saturation, lightness, alpha) { |
| 508 | if (arguments.length == 1) { |
| 509 | var hsl = hue; |
| 510 | hue = hsl.h; |
| 511 | saturation = hsl.s; |
| 512 | lightness = hsl.l; |
| 513 | alpha = hsl.a; |
| 514 | } |
| 515 | var red; |
| 516 | var green; |
| 517 | var blue; |
| 518 | if (saturation === 0) { |
| 519 | red = lightness; |
| 520 | green = lightness; |
| 521 | blue = lightness; |
| 522 | } else { |
| 523 | var m2; |
| 524 | if (lightness <= 0.5) { |
| 525 | m2 = lightness * (1.0 + saturation); |
| 526 | } else { |
| 527 | m2 = lightness + saturation - (lightness * saturation); |
| 528 | } |
| 529 | var m1 = (2.0 * lightness) - m2; |
| 530 | var f = MochiKit.Color._hslValue; |
| 531 | var h6 = hue * 6.0; |
| 532 | red = f(m1, m2, h6 + 2); |
| 533 | green = f(m1, m2, h6); |
| 534 | blue = f(m1, m2, h6 - 2); |
| 535 | } |
| 536 | return { |
| 537 | r: red, |
| 538 | g: green, |
| 539 | b: blue, |
| 540 | a: alpha |
| 541 | }; |
| 542 | }, |
| 543 | |
| 544 | /** @id MochiKit.Color.rgbToHSV */ |
| 545 | rgbToHSV: function (red, green, blue, alpha) { |
| 546 | if (arguments.length == 1) { |
| 547 | var rgb = red; |
| 548 | red = rgb.r; |
| 549 | green = rgb.g; |
| 550 | blue = rgb.b; |
| 551 | alpha = rgb.a; |
| 552 | } |
| 553 | var max = Math.max(Math.max(red, green), blue); |
| 554 | var min = Math.min(Math.min(red, green), blue); |
| 555 | var hue; |
| 556 | var saturation; |
| 557 | var value = max; |
| 558 | if (min == max) { |
| 559 | hue = 0; |
| 560 | saturation = 0; |
| 561 | } else { |
| 562 | var delta = (max - min); |
| 563 | saturation = delta / max; |
| 564 | |
| 565 | if (red == max) { |
| 566 | hue = (green - blue) / delta; |
| 567 | } else if (green == max) { |
| 568 | hue = 2 + ((blue - red) / delta); |
| 569 | } else { |
| 570 | hue = 4 + ((red - green) / delta); |
| 571 | } |
| 572 | hue /= 6; |
| 573 | if (hue < 0) { |
| 574 | hue += 1; |
| 575 | } |
| 576 | if (hue > 1) { |
| 577 | hue -= 1; |
| 578 | } |
| 579 | } |
| 580 | return { |
| 581 | h: hue, |
| 582 | s: saturation, |
| 583 | v: value, |
| 584 | a: alpha |
| 585 | }; |
| 586 | }, |
| 587 | |
| 588 | /** @id MochiKit.Color.rgbToHSL */ |
| 589 | rgbToHSL: function (red, green, blue, alpha) { |
| 590 | if (arguments.length == 1) { |
| 591 | var rgb = red; |
| 592 | red = rgb.r; |
| 593 | green = rgb.g; |
| 594 | blue = rgb.b; |
| 595 | alpha = rgb.a; |
| 596 | } |
| 597 | var max = Math.max(red, Math.max(green, blue)); |
| 598 | var min = Math.min(red, Math.min(green, blue)); |
| 599 | var hue; |
| 600 | var saturation; |
| 601 | var lightness = (max + min) / 2.0; |
| 602 | var delta = max - min; |
| 603 | if (delta === 0) { |
| 604 | hue = 0; |
| 605 | saturation = 0; |
| 606 | } else { |
| 607 | if (lightness <= 0.5) { |
| 608 | saturation = delta / (max + min); |
| 609 | } else { |
| 610 | saturation = delta / (2 - max - min); |
| 611 | } |
| 612 | if (red == max) { |
| 613 | hue = (green - blue) / delta; |
| 614 | } else if (green == max) { |
| 615 | hue = 2 + ((blue - red) / delta); |
| 616 | } else { |
| 617 | hue = 4 + ((red - green) / delta); |
| 618 | } |
| 619 | hue /= 6; |
| 620 | if (hue < 0) { |
| 621 | hue += 1; |
| 622 | } |
| 623 | if (hue > 1) { |
| 624 | hue -= 1; |
| 625 | } |
| 626 | |
| 627 | } |
| 628 | return { |
| 629 | h: hue, |
| 630 | s: saturation, |
| 631 | l: lightness, |
| 632 | a: alpha |
| 633 | }; |
| 634 | }, |
| 635 | |
| 636 | /** @id MochiKit.Color.toColorPart */ |
| 637 | toColorPart: function (num) { |
| 638 | num = Math.round(num); |
| 639 | var digits = num.toString(16); |
| 640 | if (num < 16) { |
| 641 | return '0' + digits; |
| 642 | } |
| 643 | return digits; |
| 644 | }, |
| 645 | |
| 646 | __new__: function () { |
| 647 | var m = MochiKit.Base; |
| 648 | /** @id MochiKit.Color.fromRGBString */ |
| 649 | this.Color.fromRGBString = m.bind( |
| 650 | this.Color._fromColorString, this.Color, "rgb", "fromRGB", |
| 651 | [1.0/255.0, 1.0/255.0, 1.0/255.0, 1] |
| 652 | ); |
| 653 | /** @id MochiKit.Color.fromHSLString */ |
| 654 | this.Color.fromHSLString = m.bind( |
| 655 | this.Color._fromColorString, this.Color, "hsl", "fromHSL", |
| 656 | [1.0/360.0, 0.01, 0.01, 1] |
| 657 | ); |
| 658 | |
| 659 | var third = 1.0 / 3.0; |
| 660 | /** @id MochiKit.Color.colors */ |
| 661 | var colors = { |
| 662 | // NSColor colors plus transparent |
| 663 | /** @id MochiKit.Color.blackColor */ |
| 664 | black: [0, 0, 0], |
| 665 | /** @id MochiKit.Color.blueColor */ |
| 666 | blue: [0, 0, 1], |
| 667 | /** @id MochiKit.Color.brownColor */ |
| 668 | brown: [0.6, 0.4, 0.2], |
| 669 | /** @id MochiKit.Color.cyanColor */ |
| 670 | cyan: [0, 1, 1], |
| 671 | /** @id MochiKit.Color.darkGrayColor */ |
| 672 | darkGray: [third, third, third], |
| 673 | /** @id MochiKit.Color.grayColor */ |
| 674 | gray: [0.5, 0.5, 0.5], |
| 675 | /** @id MochiKit.Color.greenColor */ |
| 676 | green: [0, 1, 0], |
| 677 | /** @id MochiKit.Color.lightGrayColor */ |
| 678 | lightGray: [2 * third, 2 * third, 2 * third], |
| 679 | /** @id MochiKit.Color.magentaColor */ |
| 680 | magenta: [1, 0, 1], |
| 681 | /** @id MochiKit.Color.orangeColor */ |
| 682 | orange: [1, 0.5, 0], |
| 683 | /** @id MochiKit.Color.purpleColor */ |
| 684 | purple: [0.5, 0, 0.5], |
| 685 | /** @id MochiKit.Color.redColor */ |
| 686 | red: [1, 0, 0], |
| 687 | /** @id MochiKit.Color.transparentColor */ |
| 688 | transparent: [0, 0, 0, 0], |
| 689 | /** @id MochiKit.Color.whiteColor */ |
| 690 | white: [1, 1, 1], |
| 691 | /** @id MochiKit.Color.yellowColor */ |
| 692 | yellow: [1, 1, 0] |
| 693 | }; |
| 694 | |
| 695 | var makeColor = function (name, r, g, b, a) { |
| 696 | var rval = this.fromRGB(r, g, b, a); |
| 697 | this[name] = function () { return rval; }; |
| 698 | return rval; |
| 699 | }; |
| 700 | |
| 701 | for (var k in colors) { |
| 702 | var name = k + "Color"; |
| 703 | var bindArgs = m.concat( |
| 704 | [makeColor, this.Color, name], |
| 705 | colors[k] |
| 706 | ); |
| 707 | this.Color[name] = m.bind.apply(null, bindArgs); |
| 708 | } |
| 709 | |
| 710 | var isColor = function () { |
| 711 | for (var i = 0; i < arguments.length; i++) { |
| 712 | if (!(arguments[i] instanceof Color)) { |
| 713 | return false; |
| 714 | } |
| 715 | } |
| 716 | return true; |
| 717 | }; |
| 718 | |
| 719 | var compareColor = function (a, b) { |
| 720 | return a.compareRGB(b); |
| 721 | }; |
| 722 | |
| 723 | m.nameFunctions(this); |
| 724 | |
| 725 | m.registerComparator(this.Color.NAME, isColor, compareColor); |
| 726 | |
| 727 | this.EXPORT_TAGS = { |
| 728 | ":common": this.EXPORT, |
| 729 | ":all": m.concat(this.EXPORT, this.EXPORT_OK) |
| 730 | }; |
| 731 | |
| 732 | } |
| 733 | }); |
| 734 | |
| 735 | MochiKit.Color.EXPORT = [ |
| 736 | "Color" |
| 737 | ]; |
| 738 | |
| 739 | MochiKit.Color.EXPORT_OK = [ |
| 740 | "clampColorComponent", |
| 741 | "rgbToHSL", |
| 742 | "hslToRGB", |
| 743 | "rgbToHSV", |
| 744 | "hsvToRGB", |
| 745 | "toColorPart" |
| 746 | ]; |
| 747 | |
| 748 | MochiKit.Color.__new__(); |
| 749 | |
| 750 | MochiKit.Base._exportSymbols(this, MochiKit.Color); |
| 751 | |
| 752 | // Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS> |
| 753 | |
| 754 | MochiKit.Color.Color._namedColors = { |
| 755 | aliceblue: "#f0f8ff", |
| 756 | antiquewhite: "#faebd7", |
| 757 | aqua: "#00ffff", |
| 758 | aquamarine: "#7fffd4", |
| 759 | azure: "#f0ffff", |
| 760 | beige: "#f5f5dc", |
| 761 | bisque: "#ffe4c4", |
| 762 | black: "#000000", |
| 763 | blanchedalmond: "#ffebcd", |
| 764 | blue: "#0000ff", |
| 765 | blueviolet: "#8a2be2", |
| 766 | brown: "#a52a2a", |
| 767 | burlywood: "#deb887", |
| 768 | cadetblue: "#5f9ea0", |
| 769 | chartreuse: "#7fff00", |
| 770 | chocolate: "#d2691e", |
| 771 | coral: "#ff7f50", |
| 772 | cornflowerblue: "#6495ed", |
| 773 | cornsilk: "#fff8dc", |
| 774 | crimson: "#dc143c", |
| 775 | cyan: "#00ffff", |
| 776 | darkblue: "#00008b", |
| 777 | darkcyan: "#008b8b", |
| 778 | darkgoldenrod: "#b8860b", |
| 779 | darkgray: "#a9a9a9", |
| 780 | darkgreen: "#006400", |
| 781 | darkgrey: "#a9a9a9", |
| 782 | darkkhaki: "#bdb76b", |
| 783 | darkmagenta: "#8b008b", |
| 784 | darkolivegreen: "#556b2f", |
| 785 | darkorange: "#ff8c00", |
| 786 | darkorchid: "#9932cc", |
| 787 | darkred: "#8b0000", |
| 788 | darksalmon: "#e9967a", |
| 789 | darkseagreen: "#8fbc8f", |
| 790 | darkslateblue: "#483d8b", |
| 791 | darkslategray: "#2f4f4f", |
| 792 | darkslategrey: "#2f4f4f", |
| 793 | darkturquoise: "#00ced1", |
| 794 | darkviolet: "#9400d3", |
| 795 | deeppink: "#ff1493", |
| 796 | deepskyblue: "#00bfff", |
| 797 | dimgray: "#696969", |
| 798 | dimgrey: "#696969", |
| 799 | dodgerblue: "#1e90ff", |
| 800 | firebrick: "#b22222", |
| 801 | floralwhite: "#fffaf0", |
| 802 | forestgreen: "#228b22", |
| 803 | fuchsia: "#ff00ff", |
| 804 | gainsboro: "#dcdcdc", |
| 805 | ghostwhite: "#f8f8ff", |
| 806 | gold: "#ffd700", |
| 807 | goldenrod: "#daa520", |
| 808 | gray: "#808080", |
| 809 | green: "#008000", |
| 810 | greenyellow: "#adff2f", |
| 811 | grey: "#808080", |
| 812 | honeydew: "#f0fff0", |
| 813 | hotpink: "#ff69b4", |
| 814 | indianred: "#cd5c5c", |
| 815 | indigo: "#4b0082", |
| 816 | ivory: "#fffff0", |
| 817 | khaki: "#f0e68c", |
| 818 | lavender: "#e6e6fa", |
| 819 | lavenderblush: "#fff0f5", |
| 820 | lawngreen: "#7cfc00", |
| 821 | lemonchiffon: "#fffacd", |
| 822 | lightblue: "#add8e6", |
| 823 | lightcoral: "#f08080", |
| 824 | lightcyan: "#e0ffff", |
| 825 | lightgoldenrodyellow: "#fafad2", |
| 826 | lightgray: "#d3d3d3", |
| 827 | lightgreen: "#90ee90", |
| 828 | lightgrey: "#d3d3d3", |
| 829 | lightpink: "#ffb6c1", |
| 830 | lightsalmon: "#ffa07a", |
| 831 | lightseagreen: "#20b2aa", |
| 832 | lightskyblue: "#87cefa", |
| 833 | lightslategray: "#778899", |
| 834 | lightslategrey: "#778899", |
| 835 | lightsteelblue: "#b0c4de", |
| 836 | lightyellow: "#ffffe0", |
| 837 | lime: "#00ff00", |
| 838 | limegreen: "#32cd32", |
| 839 | linen: "#faf0e6", |
| 840 | magenta: "#ff00ff", |
| 841 | maroon: "#800000", |
| 842 | mediumaquamarine: "#66cdaa", |
| 843 | mediumblue: "#0000cd", |
| 844 | mediumorchid: "#ba55d3", |
| 845 | mediumpurple: "#9370db", |
| 846 | mediumseagreen: "#3cb371", |
| 847 | mediumslateblue: "#7b68ee", |
| 848 | mediumspringgreen: "#00fa9a", |
| 849 | mediumturquoise: "#48d1cc", |
| 850 | mediumvioletred: "#c71585", |
| 851 | midnightblue: "#191970", |
| 852 | mintcream: "#f5fffa", |
| 853 | mistyrose: "#ffe4e1", |
| 854 | moccasin: "#ffe4b5", |
| 855 | navajowhite: "#ffdead", |
| 856 | navy: "#000080", |
| 857 | oldlace: "#fdf5e6", |
| 858 | olive: "#808000", |
| 859 | olivedrab: "#6b8e23", |
| 860 | orange: "#ffa500", |
| 861 | orangered: "#ff4500", |
| 862 | orchid: "#da70d6", |
| 863 | palegoldenrod: "#eee8aa", |
| 864 | palegreen: "#98fb98", |
| 865 | paleturquoise: "#afeeee", |
| 866 | palevioletred: "#db7093", |
| 867 | papayawhip: "#ffefd5", |
| 868 | peachpuff: "#ffdab9", |
| 869 | peru: "#cd853f", |
| 870 | pink: "#ffc0cb", |
| 871 | plum: "#dda0dd", |
| 872 | powderblue: "#b0e0e6", |
| 873 | purple: "#800080", |
| 874 | red: "#ff0000", |
| 875 | rosybrown: "#bc8f8f", |
| 876 | royalblue: "#4169e1", |
| 877 | saddlebrown: "#8b4513", |
| 878 | salmon: "#fa8072", |
| 879 | sandybrown: "#f4a460", |
| 880 | seagreen: "#2e8b57", |
| 881 | seashell: "#fff5ee", |
| 882 | sienna: "#a0522d", |
| 883 | silver: "#c0c0c0", |
| 884 | skyblue: "#87ceeb", |
| 885 | slateblue: "#6a5acd", |
| 886 | slategray: "#708090", |
| 887 | slategrey: "#708090", |
| 888 | snow: "#fffafa", |
| 889 | springgreen: "#00ff7f", |
| 890 | steelblue: "#4682b4", |
| 891 | tan: "#d2b48c", |
| 892 | teal: "#008080", |
| 893 | thistle: "#d8bfd8", |
| 894 | tomato: "#ff6347", |
| 895 | turquoise: "#40e0d0", |
| 896 | violet: "#ee82ee", |
| 897 | wheat: "#f5deb3", |
| 898 | white: "#ffffff", |
| 899 | whitesmoke: "#f5f5f5", |
| 900 | yellow: "#ffff00", |
| 901 | yellowgreen: "#9acd32" |
| 902 | }; |