summaryrefslogtreecommitdiff
path: root/modules/Color.jsm
blob: 00a9bd9534dc5f676c39c71fb1288d50e4eedef6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

this.EXPORTED_SYMBOLS = ["Color"];

/**
 * Color class, which describes a color.
 * In the future, this object may be extended to allow for conversions between
 * different color formats and notations, support transparency.
 *
 * @param {Number} r Red color component
 * @param {Number} g Green color component
 * @param {Number} b Blue color component
 */
function Color(r, g, b) {
  this.r = r;
  this.g = g;
  this.b = b;
}

Color.prototype = {
  /**
   * Formula from W3C's WCAG 2.0 spec's relative luminance, section 1.4.1,
   * http://www.w3.org/TR/WCAG20/.
   *
   * @return {Number} Relative luminance, represented as number between 0 and 1.
   */
  get relativeLuminance() {
    let colorArr = [this.r, this.b, this.g].map(color => {
      color = parseInt(color, 10);
      if (color <= 10)
        return color / 255 / 12.92;
      return Math.pow(((color / 255) + 0.055) / 1.055, 2.4);
    });
    return colorArr[0] * 0.2126 +
           colorArr[1] * 0.7152 +
           colorArr[2] * 0.0722;
  },

  /**
   * @return {Boolean} TRUE if the color value can be considered bright.
   */
  get isBright() {
    // Note: this is a high enough value to be considered as 'bright', but was
    //       decided upon empirically.
    return this.relativeLuminance > 0.7;
  },

  /**
   * Get the contrast ratio between the current color and a second other color.
   * A common use case is to express the difference between a foreground and a
   * background color in numbers.
   * Formula from W3C's WCAG 2.0 spec's contrast ratio, section 1.4.1,
   * http://www.w3.org/TR/WCAG20/.
   *
   * @param  {Color}  otherColor Color instance to calculate the contrast with
   * @return {Number} Contrast ratios can range from 1 to 21, commonly written
   *                  as 1:1 to 21:1.
   */
  contrastRatio(otherColor) {
    if (!(otherColor instanceof Color))
      throw new TypeError("The first argument should be an instance of Color");

    let luminance = this.relativeLuminance;
    let otherLuminance = otherColor.relativeLuminance;
    return (Math.max(luminance, otherLuminance) + 0.05) /
      (Math.min(luminance, otherLuminance) + 0.05);
  },

  /**
   * Biased method to check if the contrast ratio between two colors is high
   * enough to be discernable.
   *
   * @param  {Color} otherColor Color instance to calculate the contrast with
   * @return {Boolean}
   */
  isContrastRatioAcceptable(otherColor) {
    // Note: this is a high enough value to be considered as 'high contrast',
    //       but was decided upon empirically.
    return this.contrastRatio(otherColor) > 3;
  }
};