1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2009, 2010, 2012, 2013, 2014, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2009, 2010, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Creates a color object. 26 * @class 27 * This class represents a color and is useful for color operations inspired by the code in SkinResources.java. 28 * 29 */ 30 AjxColor = function(r, g, b) { 31 if (arguments.length == 0) return; 32 this.r = r; 33 this.g = g; 34 this.b = b; 35 }; 36 37 /** 38 * Returns a string representation of the object. 39 * 40 * @return {string} a string representation of the object 41 */ 42 AjxColor.prototype.toString = function() { 43 return AjxColor.color(this.r, this.g, this.b); 44 }; 45 46 // 47 // Static functions 48 // 49 50 /** 51 * Returns the RGB components (as an array) of the given color. 52 * 53 * @param {string} color the color string defined as "#rrggbb" 54 * @return {array} the color 55 */ 56 AjxColor.components = function(color) { 57 var m = AjxColor.__RE.exec(color); 58 return m ? [parseInt(m[1],16),parseInt(m[2],16),parseInt(m[3],16)] : null; 59 }; 60 61 /** 62 * Returns a color string of the form "#rrggbb" from the given color 63 * components. 64 * 65 * @param {number} r the Red component value between 0 and 255, inclusive 66 * @param {number} g the Green component value between 0 and 255, inclusive 67 * @param {number} b the Blue component value between 0 and 255, inclusive 68 * @return {string} the color string 69 */ 70 AjxColor.color = function(r, g, b) { 71 return [ 72 "#", 73 AjxColor.__pad(Number(Math.round(r)).toString(16), 2), 74 AjxColor.__pad(Number(Math.round(g)).toString(16), 2), 75 AjxColor.__pad(Number(Math.round(b)).toString(16), 2) 76 ].join(""); 77 }; 78 79 /** 80 * Returns a color string that is the inverse of the given color. 81 * 82 * @param color [string] Color value defined as "#rrggbb". 83 */ 84 //AjxColor.invert = function(color) { 85 // var n = ~parseInt(color.substr(1),16) & 0x0FFFFFF; 86 // return AjxColor.color((n >> 16) & 0x0FF, (n >> 8) & 0x0FF, n & 0x0FF); 87 //}; 88 89 /** 90 * Lightens the specified color by the given amount. 91 * 92 * @param {string} color the color value defined as "#rrggbb" 93 * @param {number} delta the amount to change 94 * @return {string} the color string 95 */ 96 AjxColor.lighten = function(color, delta) { 97 var comps = AjxColor.components(color); 98 return comps ? AjxColor.color( 99 AjxColor.__lighten(comps[0],delta), 100 AjxColor.__lighten(comps[1],delta), 101 AjxColor.__lighten(comps[2],delta) 102 ) : ""; 103 }; 104 105 /** 106 * Darkens the specified color by the given amount. 107 * 108 * @param {string} color the color value defined as "#rrggbb" 109 * @param {number} delta the amount to change 110 * @return {string} the color string 111 */ 112 AjxColor.darken = function(color, delta) { 113 var comps = AjxColor.components(color); 114 return comps ? AjxColor.color( 115 AjxColor.__darken(comps[0],delta), 116 AjxColor.__darken(comps[1],delta), 117 AjxColor.__darken(comps[2],delta) 118 ) : ""; 119 }; 120 121 /** 122 * Deepens the specified color. This operation is different than darken 123 * because it retains the brightness of the color even when it gets 124 * darker. Just making a color darker tends to result in a color that 125 * is "muddy". 126 * <p> 127 * The color is deepened by first determining the largest individual 128 * component value and then multiplying each component value by the ratio 129 * of its value to the largest value. Then, optionally, each value is 130 * multiplied by the adjustment value in order to deepen a little more 131 * or a little less. Typical adjustment values are around 1 such as .9 132 * or 1.1. 133 * 134 * @param {string} color the color value defined as "#rrggbb" 135 * @param {number} [adjustment] the multiplier adjustment 136 * @return {string} the color string 137 */ 138 AjxColor.deepen = function(color, adjustment) { 139 var comps = AjxColor.components(color); 140 var index = 0; 141 for (var i = 1; i < comps.length; i++) { 142 if (comps[i] > comps[index]) { 143 index = i; 144 } 145 } 146 for (var i = 0; i < comps.length; i++) { 147 var multiplier = comps[index] ? (comps[i] / comps[index]) : 1; 148 comps[i] = Math.floor(comps[i] * multiplier * (adjustment || 1)); 149 } 150 return AjxColor.color(comps[0],comps[1],comps[2]); 151 }; 152 153 // 154 // Private 155 // 156 157 AjxColor.__RE = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i; 158 159 AjxColor.__pad = function(value, width, prefix) { 160 if (!prefix) prefix = "0"; 161 var s = String(value); 162 for (var i = s.length; i < width; i++) { 163 s = prefix + s; 164 } 165 return s; 166 }; 167 168 AjxColor.__lighten = function(value, delta) { 169 return Math.max(0, Math.min(255, value + (255-value)*delta)); 170 }; 171 AjxColor.__darken = function(value, delta) { 172 return Math.max(0, Math.min(255, value + (1-value)*delta)); 173 }; 174