PageSourceSearch

https://www.odyssee-reisgidsen.nl/external/tinycolor.js

js odyssee-reisgidsen.nl collected 2026-10-07 23:04:33 UTC 33,061 bytes, 1,112 lines download raw bytes

vendor: 30,735 bytes, lines 1-1041
1// TinyColor v1.1.0
2// https://github.com/bgrins/TinyColor
3// Brian Grinstead, MIT License
4
5(function() {
6
7var trimLeft = /^[\s,#]+/,
8    trimRight = /\s+$/,
9    tinyCounter = 0,
10    math = Math,
11    mathRound = math.round,
12    mathMin = math.min,
13    mathMax = math.max,
14    mathRandom = math.random;
15
16var tinycolor = function tinycolor (color, opts) {
17
18    color = (color) ? color : '';
19    opts = opts || { };
20
21    // If input is already a tinycolor, return itself
22    if (color instanceof tinycolor) {
23       return color;
24    }
25    // If we are called as a function, call using new instead
26    if (!(this instanceof tinycolor)) {
27        return new tinycolor(color, opts);
28    }
29
30    var rgb = inputToRGB(color);
31    this._originalInput = color,
32    this._r = rgb.r,
33    this._g = rgb.g,
34    this._b = rgb.b,
35    this._a = rgb.a,
36    this._roundA = mathRound(100*this._a) / 100,
37    this._format = opts.format || rgb.format;
38    this._gradientType = opts.gradientType;
39
40    // Don't let the range of [0,255] come back in [0,1].
41    // Potentially lose a little bit of precision here, but will fix issues where
42    // .5 gets interpreted as half of the total, instead of half of 1
43    // If it was supposed to be 128, this was already taken care of by `inputToRgb`
44    if (this._r < 1) { this._r = mathRound(this._r); }
45    if (this._g < 1) { this._g = mathRound(this._g); }
46    if (this._b < 1) { this._b = mathRound(this._b); }
47
48    this._ok = rgb.ok;
49    this._tc_id = tinyCounter++;
50};
51
52tinycolor.prototype = {
53    isDark: function() {
54        return this.getBrightness() < 128;
55    },
56    isLight: function() {
57        return !this.isDark();
58    },
59    isValid: function() {
60        return this._ok;
61    },
62    getOriginalInput: function() {
63      return this._originalInput;
64    },
65    getFormat: function() {
66        return this._format;
67    },
68    getAlpha: function() {
69        return this._a;
70    },
71    getBrightness: function() {
72        var rgb = this.toRgb();
73        return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
74    },
75    setAlpha: function(value) {
76        this._a = boundAlpha(value);
77        this._roundA = mathRound(100*this._a) / 100;
78        return this;
79    },
80    toHsv: function() {
81        var hsv = rgbToHsv(this._r, this._g, this._b);
82        return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
83    },
84    toHsvString: function() {
85        var hsv = rgbToHsv(this._r, this._g, this._b);
86        var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
87        return (this._a == 1) ?
88          "hsv("  + h + ", " + s + "%, " + v + "%)" :
89          "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
90    },
91    toHsl: function() {
92        var hsl = rgbToHsl(this._r, this._g, this._b);
93        return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
94    },
95    toHslString: function() {
96        var hsl = rgbToHsl(this._r, this._g, this._b);
97        var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
98        return (this._a == 1) ?
99          "hsl("  + h + ", " + s + "%, " + l + "%)" :
100          "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
101    },
102    toHex: function(allow3Char) {
103        return rgbToHex(this._r, this._g, this._b, allow3Char);
104    },
105    toHexString: function(allow3Char) {
106        return '#' + this.toHex(allow3Char);
107    },
108    toHex8: function() {
109        return rgbaToHex(this._r, this._g, this._b, this._a);
110    },
111    toHex8String: function() {
112        return '#' + this.toHex8();
113    },
114    toRgb: function() {
115        return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
116    },
117    toRgbString: function() {
118        return (this._a == 1) ?
119          "rgb("  + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
120          "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
121    },
122    toPercentageRgb: function() {
123        return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
124    },
125    toPercentageRgbString: function() {
126        return (this._a == 1) ?
127          "rgb("  + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
128          "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
129    },
130    toName: function() {
131        if (this._a === 0) {
132            return "transparent";
133        }
134
135        if (this._a < 1) {
136            return false;
137        }
138
139        return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
140    },
141    toFilter: function(secondColor) {
142        var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
143        var secondHex8String = hex8String;
144        var gradientType = this._gradientType ? "GradientType = 1, " : "";
145
146        if (secondColor) {
147            var s = tinycolor(secondColor);
148            secondHex8String = s.toHex8String();
149        }
150
151        return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
152    },
153    toString: function(format) {
154        var formatSet = !!format;
155        format = format || this._format;
156
157        var formattedString = false;
158        var hasAlpha = this._a < 1 && this._a >= 0;
159        var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
160
161        if (needsAlphaFormat) {
162            // Special case for "transparent", all other non-alpha formats
163            // will return rgba when there is transparency.
164            if (format === "name" && this._a === 0) {
165                return this.toName();
166            }
167            return this.toRgbString();
168        }
169        if (format === "rgb") {
170            formattedString = this.toRgbString();
171        }
172        if (format === "prgb") {
173            formattedString = this.toPercentageRgbString();
174        }
175        if (format === "hex" || format === "hex6") {
176            formattedString = this.toHexString();
177        }
178        if (format === "hex3") {
179            formattedString = this.toHexString(true);
180        }
181        if (format === "hex8") {
182            formattedString = this.toHex8String();
183        }
184        if (format === "name") {
185            formattedString = this.toName();
186        }
187        if (format === "hsl") {
188            formattedString = this.toHslString();
189        }
190        if (format === "hsv") {
191            formattedString = this.toHsvString();
192        }
193
194        return formattedString || this.toHexString();
195    },
196
197    _applyModification: function(fn, args) {
198        var color = fn.apply(null, [this].concat([].slice.call(args)));
199        this._r = color._r;
200        this._g = color._g;
201        this._b = color._b;
202        this.setAlpha(color._a);
203        return this;
204    },
205    lighten: function() {
206        return this._applyModification(lighten, arguments);
207    },
208    brighten: function() {
209        return this._applyModification(brighten, arguments);
210    },
211    darken: function() {
212        return this._applyModification(darken, arguments);
213    },
214    desaturate: function() {
215        return this._applyModification(desaturate, arguments);
216    },
217    saturate: function() {
218        return this._applyModification(saturate, arguments);
219    },
220    greyscale: function() {
221        return this._applyModification(greyscale, arguments);
222    },
223    spin: function() {
224        return this._applyModification(spin, arguments);
225    },
226
227    _applyCombination: function(fn, args) {
228        return fn.apply(null, [this].concat([].slice.call(args)));
229    },
230    analogous: function() {
231        return this._applyCombination(analogous, arguments);
232    },
233    complement: function() {
234        return this._applyCombination(complement, arguments);
235    },
236    monochromatic: function() {
237        return this._applyCombination(monochromatic, arguments);
238    },
239    splitcomplement: function() {
240        return this._applyCombination(splitcomplement, arguments);
241    },
242    triad: function() {
243        return this._applyCombination(triad, arguments);
244    },
245    tetrad: function() {
246        return this._applyCombination(tetrad, arguments);
247    }
248};
249
250// If input is an object, force 1 into "1.0" to handle ratios properly
251// String input requires "1.0" as input, so 1 will be treated as 1
252tinycolor.fromRatio = function(color, opts) {
253    if (typeof color == "object") {
254        var newColor = {};
255        for (var i in color) {
256            if (color.hasOwnProperty(i)) {
257                if (i === "a") {
258                    newColor[i] = color[i];
259                }
260                else {
261                    newColor[i] = convertToPercentage(color[i]);
262                }
263            }
264        }
265        color = newColor;
266    }
267
268    return tinycolor(color, opts);
269};
270
271// Given a string or object, convert that input to RGB
272// Possible string inputs:
273//
274//     "red"
275//     "#f00" or "f00"
276//     "#ff0000" or "ff0000"
277//     "#ff000000" or "ff000000"
278//     "rgb 255 0 0" or "rgb (255, 0, 0)"
279//     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
280//     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
281//     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
282//     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
283//     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
284//     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
285//
286function inputToRGB(color) {
287
288    var rgb = { r: 0, g: 0, b: 0 };
289    var a = 1;
290    var ok = false;
291    var format = false;
292
293    if (typeof color == "string") {
294        color = stringInputToObject(color);
295    }
296
297    if (typeof color == "object") {
298        if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
299            rgb = rgbToRgb(color.r, color.g, color.b);
300            ok = true;
301            format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
302        }
303        else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
304            color.s = convertToPercentage(color.s);
305            color.v = convertToPercentage(color.v);
306            rgb = hsvToRgb(color.h, color.s, color.v);
307            ok = true;
308            format = "hsv";
309        }
310        else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
311            color.s = convertToPercentage(color.s);
312            color.l = convertToPercentage(color.l);
313            rgb = hslToRgb(color.h, color.s, color.l);
314            ok = true;
315            format = "hsl";
316        }
317
318        if (color.hasOwnProperty("a")) {
319            a = color.a;
320        }
321    }
322
323    a = boundAlpha(a);
324
325    return {
326        ok: ok,
327        format: color.format || format,
328        r: mathMin(255, mathMax(rgb.r, 0)),
329        g: mathMin(255, mathMax(rgb.g, 0)),
330        b: mathMin(255, mathMax(rgb.b, 0)),
331        a: a
332    };
333}
334
335
336// Conversion Functions
337// --------------------
338
339// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
340// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
341
342// `rgbToRgb`
343// Handle bounds / percentage checking to conform to CSS color spec
344// <http://www.w3.org/TR/css3-color/>
345// *Assumes:* r, g, b in [0, 255] or [0, 1]
346// *Returns:* { r, g, b } in [0, 255]
347function rgbToRgb(r, g, b){
348    return {
349        r: bound01(r, 255) * 255,
350        g: bound01(g, 255) * 255,
351        b: bound01(b, 255) * 255
352    };
353}
354
355// `rgbToHsl`
356// Converts an RGB color value to HSL.
357// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
358// *Returns:* { h, s, l } in [0,1]
359function rgbToHsl(r, g, b) {
360
361    r = bound01(r, 255);
362    g = bound01(g, 255);
363    b = bound01(b, 255);
364
365    var max = mathMax(r, g, b), min = mathMin(r, g, b);
366    var h, s, l = (max + min) / 2;
367
368    if(max == min) {
369        h = s = 0; // achromatic
370    }
371    else {
372        var d = max - min;
373        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
374        switch(max) {
375            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
376            case g: h = (b - r) / d + 2; break;
377            case b: h = (r - g) / d + 4; break;
378        }
379
380        h /= 6;
381    }
382
383    return { h: h, s: s, l: l };
384}
385
386// `hslToRgb`
387// Converts an HSL color value to RGB.
388// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
389// *Returns:* { r, g, b } in the set [0, 255]
390function hslToRgb(h, s, l) {
391    var r, g, b;
392
393    h = bound01(h, 360);
394    s = bound01(s, 100);
395    l = bound01(l, 100);
396
397    function hue2rgb(p, q, t) {
398        if(t < 0) t += 1;
399        if(t > 1) t -= 1;
400        if(t < 1/6) return p + (q - p) * 6 * t;
401        if(t < 1/2) return q;
402        if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
403        return p;
404    }
405
406    if(s === 0) {
407        r = g = b = l; // achromatic
408    }
409    else {
410        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
411        var p = 2 * l - q;
412        r = hue2rgb(p, q, h + 1/3);
413        g = hue2rgb(p, q, h);
414        b = hue2rgb(p, q, h - 1/3);
415    }
416
417    return { r: r * 255, g: g * 255, b: b * 255 };
418}
419
420// `rgbToHsv`
421// Converts an RGB color value to HSV
422// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
423// *Returns:* { h, s, v } in [0,1]
424function rgbToHsv(r, g, b) {
425
426    r = bound01(r, 255);
427    g = bound01(g, 255);
428    b = bound01(b, 255);
429
430    var max = mathMax(r, g, b), min = mathMin(r, g, b);
431    var h, s, v = max;
432
433    var d = max - min;
434    s = max === 0 ? 0 : d / max;
435
436    if(max == min) {
437        h = 0; // achromatic
438    }
439    else {
440        switch(max) {
441            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
442            case g: h = (b - r) / d + 2; break;
443            case b: h = (r - g) / d + 4; break;
444        }
445        h /= 6;
446    }
447    return { h: h, s: s, v: v };
448}
449
450// `hsvToRgb`
451// Converts an HSV color value to RGB.
452// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
453// *Returns:* { r, g, b } in the set [0, 255]
454 function hsvToRgb(h, s, v) {
455
456    h = bound01(h, 360) * 6;
457    s = bound01(s, 100);
458    v = bound01(v, 100);
459
460    var i = math.floor(h),
461        f = h - i,
462        p = v * (1 - s),
463        q = v * (1 - f * s),
464        t = v * (1 - (1 - f) * s),
465        mod = i % 6,
466        r = [v, q, p, p, t, v][mod],
467        g = [t, v, v, q, p, p][mod],
468        b = [p, p, t, v, v, q][mod];
469
470    return { r: r * 255, g: g * 255, b: b * 255 };
471}
472
473// `rgbToHex`
474// Converts an RGB color to hex
475// Assumes r, g, and b are contained in the set [0, 255]
476// Returns a 3 or 6 character hex
477function rgbToHex(r, g, b, allow3Char) {
478
479    var hex = [
480        pad2(mathRound(r).toString(16)),
481        pad2(mathRound(g).toString(16)),
482        pad2(mathRound(b).toString(16))
483    ];
484
485    // Return a 3 character hex if possible
486    if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
487        return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
488    }
489
490    return hex.join("");
491}
492    // `rgbaToHex`
493    // Converts an RGBA color plus alpha transparency to hex
494    // Assumes r, g, b and a are contained in the set [0, 255]
495    // Returns an 8 character hex
496    function rgbaToHex(r, g, b, a) {
497
498        var hex = [
499            pad2(convertDecimalToHex(a)),
500            pad2(mathRound(r).toString(16)),
501            pad2(mathRound(g).toString(16)),
502            pad2(mathRound(b).toString(16))
503        ];
504
505        return hex.join("");
506    }
507
508// `equals`
509// Can be called with any tinycolor input
510tinycolor.equals = function (color1, color2) {
511    if (!color1 || !color2) { return false; }
512    return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
513};
514tinycolor.random = function() {
515    return tinycolor.fromRatio({
516        r: mathRandom(),
517        g: mathRandom(),
518        b: mathRandom()
519    });
520};
521
522
523// Modification Functions
524// ----------------------
525// Thanks to less.js for some of the basics here
526// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
527
528function desaturate(color, amount) {
529    amount = (amount === 0) ? 0 : (amount || 10);
530    var hsl = tinycolor(color).toHsl();
531    hsl.s -= amount / 100;
532    hsl.s = clamp01(hsl.s);
533    return tinycolor(hsl);
534}
535
536function saturate(color, amount) {
537    amount = (amount === 0) ? 0 : (amount || 10);
538    var hsl = tinycolor(color).toHsl();
539    hsl.s += amount / 100;
540    hsl.s = clamp01(hsl.s);
541    return tinycolor(hsl);
542}
543
544function greyscale(color) {
545    return tinycolor(color).desaturate(100);
546}
547
548function lighten (color, amount) {
549    amount = (amount === 0) ? 0 : (amount || 10);
550    var hsl = tinycolor(color).toHsl();
551    hsl.l += amount / 100;
552    hsl.l = clamp01(hsl.l);
553    return tinycolor(hsl);
554}
555
556function brighten(color, amount) {
557    amount = (amount === 0) ? 0 : (amount || 10);
558    var rgb = tinycolor(color).toRgb();
559    rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
560    rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
561    rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
562    return tinycolor(rgb);
563}
564
565function darken (color, amount) {
566    amount = (amount === 0) ? 0 : (amount || 10);
567    var hsl = tinycolor(color).toHsl();
568    hsl.l -= amount / 100;
569    hsl.l = clamp01(hsl.l);
570    return tinycolor(hsl);
571}
572
573// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
574// Values outside of this range will be wrapped into this range.
575function spin(color, amount) {
576    var hsl = tinycolor(color).toHsl();
577    var hue = (mathRound(hsl.h) + amount) % 360;
578    hsl.h = hue < 0 ? 360 + hue : hue;
579    return tinycolor(hsl);
580}
581
582// Combination Functions
583// ---------------------
584// Thanks to jQuery xColor for some of the ideas behind these
585// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
586
587function complement(color) {
588    var hsl = tinycolor(color).toHsl();
589    hsl.h = (hsl.h + 180) % 360;
590    return tinycolor(hsl);
591}
592
593function triad(color) {
594    var hsl = tinycolor(color).toHsl();
595    var h = hsl.h;
596    return [
597        tinycolor(color),
598        tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
599        tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
600    ];
601}
602
603function tetrad(color) {
604    var hsl = tinycolor(color).toHsl();
605    var h = hsl.h;
606    return [
607        tinycolor(color),
608        tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
609        tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
610        tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
611    ];
612}
613
614function splitcomplement(color) {
615    var hsl = tinycolor(color).toHsl();
616    var h = hsl.h;
617    return [
618        tinycolor(color),
619        tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
620        tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
621    ];
622}
623
624function analogous(color, results, slices) {
625    results = results || 6;
626    slices = slices || 30;
627
628    var hsl = tinycolor(color).toHsl();
629    var part = 360 / slices;
630    var ret = [tinycolor(color)];
631
632    for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
633        hsl.h = (hsl.h + part) % 360;
634        ret.push(tinycolor(hsl));
635    }
636    return ret;
637}
638
639function monochromatic(color, results) {
640    results = results || 6;
641    var hsv = tinycolor(color).toHsv();
642    var h = hsv.h, s = hsv.s, v = hsv.v;
643    var ret = [];
644    var modification = 1 / results;
645
646    while (results--) {
647        ret.push(tinycolor({ h: h, s: s, v: v}));
648        v = (v + modification) % 1;
649    }
650
651    return ret;
652}
653
654// Utility Functions
655// ---------------------
656
657tinycolor.mix = function(color1, color2, amount) {
658    amount = (amount === 0) ? 0 : (amount || 50);
659
660    var rgb1 = tinycolor(color1).toRgb();
661    var rgb2 = tinycolor(color2).toRgb();
662
663    var p = amount / 100;
664    var w = p * 2 - 1;
665    var a = rgb2.a - rgb1.a;
666
667    var w1;
668
669    if (w * a == -1) {
670        w1 = w;
671    } else {
672        w1 = (w + a) / (1 + w * a);
673    }
674
675    w1 = (w1 + 1) / 2;
676
677    var w2 = 1 - w1;
678
679    var rgba = {
680        r: rgb2.r * w1 + rgb1.r * w2,
681        g: rgb2.g * w1 + rgb1.g * w2,
682        b: rgb2.b * w1 + rgb1.b * w2,
683        a: rgb2.a * p  + rgb1.a * (1 - p)
684    };
685
686    return tinycolor(rgba);
687};
688
689
690// Readability Functions
691// ---------------------
692// <http://www.w3.org/TR/AERT#color-contrast>
693
694// `readability`
695// Analyze the 2 colors and returns an object with the following properties:
696//    `brightness`: difference in brightness between the two colors
697//    `color`: difference in color/hue between the two colors
698tinycolor.readability = function(color1, color2) {
699    var c1 = tinycolor(color1);
700    var c2 = tinycolor(color2);
701    var rgb1 = c1.toRgb();
702    var rgb2 = c2.toRgb();
703    var brightnessA = c1.getBrightness();
704    var brightnessB = c2.getBrightness();
705    var colorDiff = (
706        Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
707        Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
708        Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
709    );
710
711    return {
712        brightness: Math.abs(brightnessA - brightnessB),
713        color: colorDiff
714    };
715};
716
717// `readable`
718// http://www.w3.org/TR/AERT#color-contrast
719// Ensure that foreground and background color combinations provide sufficient contrast.
720// *Example*
721//    tinycolor.isReadable("#000", "#111") => false
722tinycolor.isReadable = function(color1, color2) {
723    var readability = tinycolor.readability(color1, color2);
724    return readability.brightness > 125 && readability.color > 500;
725};
726
727// `mostReadable`
728// Given a base color and a list of possible foreground or background
729// colors for that base, returns the most readable color.
730// *Example*
731//    tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
732tinycolor.mostReadable = function(baseColor, colorList) {
733    var bestColor = null;
734    var bestScore = 0;
735    var bestIsReadable = false;
736    for (var i=0; i < colorList.length; i++) {
737
738        // We normalize both around the "acceptable" breaking point,
739        // but rank brightness constrast higher than hue.
740
741        var readability = tinycolor.readability(baseColor, colorList[i]);
742        var readable = readability.brightness > 125 && readability.color > 500;
743        var score = 3 * (readability.brightness / 125) + (readability.color / 500);
744
745        if ((readable && ! bestIsReadable) ||
746            (readable && bestIsReadable && score > bestScore) ||
747            ((! readable) && (! bestIsReadable) && score > bestScore)) {
748            bestIsReadable = readable;
749            bestScore = score;
750            bestColor = tinycolor(colorList[i]);
751        }
752    }
753    return bestColor;
754};
755
756
757// Big List of Colors
758// ------------------
759// <http://www.w3.org/TR/css3-color/#svg-color>
760var names = tinycolor.names = {
761    aliceblue: "f0f8ff",
762    antiquewhite: "faebd7",
763    aqua: "0ff",
764    aquamarine: "7fffd4",
765    azure: "f0ffff",
766    beige: "f5f5dc",
767    bisque: "ffe4c4",
768    black: "000",
769    blanchedalmond: "ffebcd",
770    blue: "00f",
771    blueviolet: "8a2be2",
772    brown: "a52a2a",
773    burlywood: "deb887",
774    burntsienna: "ea7e5d",
775    cadetblue: "5f9ea0",
776    chartreuse: "7fff00",
777    chocolate: "d2691e",
778    coral: "ff7f50",
779    cornflowerblue: "6495ed",
780    cornsilk: "fff8dc",
781    crimson: "dc143c",
782    cyan: "0ff",
783    darkblue: "00008b",
784    darkcyan: "008b8b",
785    darkgoldenrod: "b8860b",
786    darkgray: "a9a9a9",
787    darkgreen: "006400",
788    darkgrey: "a9a9a9",
789    darkkhaki: "bdb76b",
790    darkmagenta: "8b008b",
791    darkolivegreen: "556b2f",
792    darkorange: "ff8c00",
793    darkorchid: "9932cc",
794    darkred: "8b0000",
795    darksalmon: "e9967a",
796    darkseagreen: "8fbc8f",
797    darkslateblue: "483d8b",
798    darkslategray: "2f4f4f",
799    darkslategrey: "2f4f4f",
800    darkturquoise: "00ced1",
801    darkviolet: "9400d3",
802    deeppink: "ff1493",
803    deepskyblue: "00bfff",
804    dimgray: "696969",
805    dimgrey: "696969",
806    dodgerblue: "1e90ff",
807    firebrick: "b22222",
808    floralwhite: "fffaf0",
809    forestgreen: "228b22",
810    fuchsia: "f0f",
811    gainsboro: "dcdcdc",
812    ghostwhite: "f8f8ff",
813    gold: "ffd700",
814    goldenrod: "daa520",
815    gray: "808080",
816    green: "008000",
817    greenyellow: "adff2f",
818    grey: "808080",
819    honeydew: "f0fff0",
820    hotpink: "ff69b4",
821    indianred: "cd5c5c",
822    indigo: "4b0082",
823    ivory: "fffff0",
824    khaki: "f0e68c",
825    lavender: "e6e6fa",
826    lavenderblush: "fff0f5",
827    lawngreen: "7cfc00",
828    lemonchiffon: "fffacd",
829    lightblue: "add8e6",
830    lightcoral: "f08080",
831    lightcyan: "e0ffff",
832    lightgoldenrodyellow: "fafad2",
833    lightgray: "d3d3d3",
834    lightgreen: "90ee90",
835    lightgrey: "d3d3d3",
836    lightpink: "ffb6c1",
837    lightsalmon: "ffa07a",
838    lightseagreen: "20b2aa",
839    lightskyblue: "87cefa",
840    lightslategray: "789",
841    lightslategrey: "789",
842    lightsteelblue: "b0c4de",
843    lightyellow: "ffffe0",
844    lime: "0f0",
845    limegreen: "32cd32",
846    linen: "faf0e6",
847    magenta: "f0f",
848    maroon: "800000",
849    mediumaquamarine: "66cdaa",
850    mediumblue: "0000cd",
851    mediumorchid: "ba55d3",
852    mediumpurple: "9370db",
853    mediumseagreen: "3cb371",
854    mediumslateblue: "7b68ee",
855    mediumspringgreen: "00fa9a",
856    mediumturquoise: "48d1cc",
857    mediumvioletred: "c71585",
858    midnightblue: "191970",
859    mintcream: "f5fffa",
860    mistyrose: "ffe4e1",
861    moccasin: "ffe4b5",
862    navajowhite: "ffdead",
863    navy: "000080",
864    oldlace: "fdf5e6",
865    olive: "808000",
866    olivedrab: "6b8e23",
867    orange: "ffa500",
868    orangered: "ff4500",
869    orchid: "da70d6",
870    palegoldenrod: "eee8aa",
871    palegreen: "98fb98",
872    paleturquoise: "afeeee",
873    palevioletred: "db7093",
874    papayawhip: "ffefd5",
875    peachpuff: "ffdab9",
876    peru: "cd853f",
877    pink: "ffc0cb",
878    plum: "dda0dd",
879    powderblue: "b0e0e6",
880    purple: "800080",
881    rebeccapurple: "663399",
882    red: "f00",
883    rosybrown: "bc8f8f",
884    royalblue: "4169e1",
885    saddlebrown: "8b4513",
886    salmon: "fa8072",
887    sandybrown: "f4a460",
888    seagreen: "2e8b57",
889    seashell: "fff5ee",
890    sienna: "a0522d",
891    silver: "c0c0c0",
892    skyblue: "87ceeb",
893    slateblue: "6a5acd",
894    slategray: "708090",
895    slategrey: "708090",
896    snow: "fffafa",
897    springgreen: "00ff7f",
898    steelblue: "4682b4",
899    tan: "d2b48c",
900    teal: "008080",
901    thistle: "d8bfd8",
902    tomato: "ff6347",
903    turquoise: "40e0d0",
904    violet: "ee82ee",
905    wheat: "f5deb3",
906    white: "fff",
907    whitesmoke: "f5f5f5",
908    yellow: "ff0",
909    yellowgreen: "9acd32"
910};
911
912// Make it easy to access colors via `hexNames[hex]`
913var hexNames = tinycolor.hexNames = flip(names);
914
915
916// Utilities
917// ---------
918
919// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
920function flip(o) {
921    var flipped = { };
922    for (var i in o) {
923        if (o.hasOwnProperty(i)) {
924            flipped[o[i]] = i;
925        }
926    }
927    return flipped;
928}
929
930// Return a valid alpha value [0,1] with all invalid values being set to 1
931function boundAlpha(a) {
932    a = parseFloat(a);
933
934    if (isNaN(a) || a < 0 || a > 1) {
935        a = 1;
936    }
937
938    return a;
939}
940
941// Take input from [0, n] and return it as [0, 1]
942function bound01(n, max) {
943    if (isOnePointZero(n)) { n = "100%"; }
944
945    var processPercent = isPercentage(n);
946    n = mathMin(max, mathMax(0, parseFloat(n)));
947
948    // Automatically convert percentage into number
949    if (processPercent) {
950        n = parseInt(n * max, 10) / 100;
951    }
952
953    // Handle floating point rounding errors
954    if ((math.abs(n - max) < 0.000001)) {
955        return 1;
956    }
957
958    // Convert into [0, 1] range if it isn't already
959    return (n % max) / parseFloat(max);
960}
961
962// Force a number between 0 and 1
963function clamp01(val) {
964    return mathMin(1, mathMax(0, val));
965}
966
967// Parse a base-16 hex value into a base-10 integer
968function parseIntFromHex(val) {
969    return parseInt(val, 16);
970}
971
972// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
973// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
974function isOnePointZero(n) {
975    return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
976}
977
978// Check to see if string passed in is a percentage
979function isPercentage(n) {
980    return typeof n === "string" && n.indexOf('%') != -1;
981}
982
983// Force a hex value to have 2 characters
984function pad2(c) {
985    return c.length == 1 ? '0' + c : '' + c;
986}
987
988// Replace a decimal with it's percentage value
989function convertToPercentage(n) {
990    if (n <= 1) {
991        n = (n * 100) + "%";
992    }
993
994    return n;
995}
996
997// Converts a decimal to a hex value
998function convertDecimalToHex(d) {
999    return Math.round(parseFloat(d) * 255).toString(16);
1000}
1001// Converts a hex value to a decimal
1002function convertHexToDecimal(h) {
1003    return (parseIntFromHex(h) / 255);
1004}
1005
1006var matchers = (function() {
1007
1008    // <http://www.w3.org/TR/css3-values/#integers>
1009    var CSS_INTEGER = "[-\\+]?\\d+%?";
1010
1011    // <http://www.w3.org/TR/css3-values/#number-value>
1012    var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
1013
1014    // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
1015    var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
1016
1017    // Actual matching.
1018    // Parentheses and commas are optional, but not required.
1019    // Whitespace can take the place of commas or opening paren
1020    var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
1021    var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
1022
1023    return {
1024        rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
1025        rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
1026        hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
1027        hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
1028        hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
1029        hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
1030        hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
1031        hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
1032    };
1033})();
1034
1035// `stringInputToObject`
1036// Permissive string parsing.  Take in a number of formats, and output an object
1037// based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
1038function stringInputToObject(color) {
1039
1040    color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
1041    var named = false;
vendor: 2,326 bytes, lines 1042-1112
1042    if (names[color]) {
1043        color = names[color];
1044        named = true;
1045    }
1046    else if (color == 'transparent') {
1047        return { r: 0, g: 0, b: 0, a: 0, format: "name" };
1048    }
1049
1050    // Try to match string input using regular expressions.
1051    // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
1052    // Just return an object and let the conversion functions handle that.
1053    // This way the result will be the same whether the tinycolor is initialized with string or object.
1054    var match;
1055    if ((match = matchers.rgb.exec(color))) {
1056        return { r: match[1], g: match[2], b: match[3] };
1057    }
1058    if ((match = matchers.rgba.exec(color))) {
1059        return { r: match[1], g: match[2], b: match[3], a: match[4] };
1060    }
1061    if ((match = matchers.hsl.exec(color))) {
1062        return { h: match[1], s: match[2], l: match[3] };
1063    }
1064    if ((match = matchers.hsla.exec(color))) {
1065        return { h: match[1], s: match[2], l: match[3], a: match[4] };
1066    }
1067    if ((match = matchers.hsv.exec(color))) {
1068        return { h: match[1], s: match[2], v: match[3] };
1069    }
1070    if ((match = matchers.hex8.exec(color))) {
1071        return {
1072            a: convertHexToDecimal(match[1]),
1073            r: parseIntFromHex(match[2]),
1074            g: parseIntFromHex(match[3]),
1075            b: parseIntFromHex(match[4]),
1076            format: named ? "name" : "hex8"
1077        };
1078    }
1079    if ((match = matchers.hex6.exec(color))) {
1080        return {
1081            r: parseIntFromHex(match[1]),
1082            g: parseIntFromHex(match[2]),
1083            b: parseIntFromHex(match[3]),
1084            format: named ? "name" : "hex"
1085        };
1086    }
1087    if ((match = matchers.hex3.exec(color))) {
1088        return {
1089            r: parseIntFromHex(match[1] + '' + match[1]),
1090            g: parseIntFromHex(match[2] + '' + match[2]),
1091            b: parseIntFromHex(match[3] + '' + match[3]),
1092            format: named ? "name" : "hex"
1093        };
1094    }
1095
1096    return false;
1097}
1098
1099// Node: Export function
1100if (typeof module !== "undefined" && module.exports) {
1101    module.exports = tinycolor;
1102}
1103// AMD/requirejs: Define the module
1104else if (typeof define === 'function' && define.amd) {
1105    define(function () {return tinycolor;});
1106}
1107// Browser: Expose to window
1108else {
1109    window.tinycolor = tinycolor;
1110}
1111
1112})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.