1<!DOCTYPE html> 2<!-- 3Copyright (c) 2014 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7<link rel="import" href="/tracing/base/base.html"> 8<script> 9'use strict'; 10 11tr.exportTo('tr.b', function() { 12 function clamp01(value) { 13 return Math.max(0, Math.min(1, value)); 14 } 15 16 function Color(opt_r, opt_g, opt_b, opt_a) { 17 this.r = Math.floor(opt_r) || 0; 18 this.g = Math.floor(opt_g) || 0; 19 this.b = Math.floor(opt_b) || 0; 20 this.a = opt_a; 21 } 22 23 Color.fromString = function(str) { 24 var tmp; 25 var values; 26 if (str.substr(0, 4) == 'rgb(') { 27 tmp = str.substr(4, str.length - 5); 28 values = tmp.split(',').map(function(v) { 29 return v.replace(/^\s+/, '', 'g'); 30 }); 31 if (values.length != 3) 32 throw new Error('Malformatted rgb-expression'); 33 return new Color( 34 parseInt(values[0]), 35 parseInt(values[1]), 36 parseInt(values[2])); 37 } else if (str.substr(0, 5) == 'rgba(') { 38 tmp = str.substr(5, str.length - 6); 39 values = tmp.split(',').map(function(v) { 40 return v.replace(/^\s+/, '', 'g'); 41 }); 42 if (values.length != 4) 43 throw new Error('Malformatted rgb-expression'); 44 return new Color( 45 parseInt(values[0]), 46 parseInt(values[1]), 47 parseInt(values[2]), 48 parseFloat(values[3])); 49 } else if (str[0] == '#' && str.length == 7) { 50 return new Color( 51 parseInt(str.substr(1, 2), 16), 52 parseInt(str.substr(3, 2), 16), 53 parseInt(str.substr(5, 2), 16)); 54 } else { 55 throw new Error('Unrecognized string format.'); 56 } 57 }; 58 59 Color.lerp = function(a, b, percent) { 60 if (a.a !== undefined && b.a !== undefined) 61 return Color.lerpRGBA(a, b, percent); 62 return Color.lerpRGB(a, b, percent); 63 }; 64 65 Color.lerpRGB = function(a, b, percent) { 66 return new Color( 67 ((b.r - a.r) * percent) + a.r, 68 ((b.g - a.g) * percent) + a.g, 69 ((b.b - a.b) * percent) + a.b); 70 }; 71 72 Color.lerpRGBA = function(a, b, percent) { 73 return new Color( 74 ((b.r - a.r) * percent) + a.r, 75 ((b.g - a.g) * percent) + a.g, 76 ((b.b - a.b) * percent) + a.b, 77 ((b.a - a.a) * percent) + a.a); 78 }; 79 80 Color.fromDict = function(dict) { 81 return new Color(dict.r, dict.g, dict.b, dict.a); 82 }; 83 84 /** 85 * Converts an HSL triplet with alpha to an RGB color. 86 * |h| Hue value in [0, 1]. 87 * |s| Saturation value in [0, 1]. 88 * |l| Lightness in [0, 1]. 89 * |a| Alpha in [0, 1] 90 */ 91 Color.fromHSLExplicit = function(h, s, l, a) { 92 var r, g, b; 93 function hue2rgb(p, q, t) { 94 if (t < 0) t += 1; 95 if (t > 1) t -= 1; 96 if (t < 1 / 6) return p + (q - p) * 6 * t; 97 if (t < 1 / 2) return q; 98 if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 99 return p; 100 } 101 102 if (s === 0) { 103 r = g = b = l; 104 } else { 105 var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 106 var p = 2 * l - q; 107 r = hue2rgb(p, q, h + 1 / 3); 108 g = hue2rgb(p, q, h); 109 b = hue2rgb(p, q, h - 1 / 3); 110 } 111 112 return new Color(Math.floor(r * 255), 113 Math.floor(g * 255), 114 Math.floor(b * 255), a); 115 } 116 117 Color.fromHSL = function(hsl) { 118 return Color.fromHSLExplicit(hsl.h, hsl.s, hsl.l, hsl.a); 119 } 120 121 Color.prototype = { 122 clone: function() { 123 var c = new Color(); 124 c.r = this.r; 125 c.g = this.g; 126 c.b = this.b; 127 c.a = this.a; 128 return c; 129 }, 130 131 blendOver: function(bgColor) { 132 var oneMinusThisAlpha = 1 - this.a; 133 var outA = this.a + bgColor.a * oneMinusThisAlpha; 134 var bgBlend = (bgColor.a * oneMinusThisAlpha) / bgColor.a; 135 return new Color( 136 this.r * this.a + bgColor.r * bgBlend, 137 this.g * this.a + bgColor.g * bgBlend, 138 this.b * this.a + bgColor.b * bgBlend, 139 outA); 140 }, 141 142 brighten: function(opt_k) { 143 var k; 144 k = opt_k || 0.45; 145 146 return new Color( 147 Math.min(255, this.r + Math.floor(this.r * k)), 148 Math.min(255, this.g + Math.floor(this.g * k)), 149 Math.min(255, this.b + Math.floor(this.b * k)), 150 this.a); 151 }, 152 153 lighten: function(k, opt_max_l) { 154 var max_l = opt_max_l !== undefined ? opt_max_l : 1.0; 155 var hsl = this.toHSL(); 156 hsl.l = clamp01(hsl.l + k); 157 return Color.fromHSL(hsl); 158 }, 159 160 darken: function(opt_k) { 161 var k; 162 if (opt_k !== undefined) 163 k = opt_k; 164 else 165 k = 0.45; 166 167 return new Color( 168 Math.min(255, this.r - Math.floor(this.r * k)), 169 Math.min(255, this.g - Math.floor(this.g * k)), 170 Math.min(255, this.b - Math.floor(this.b * k)), 171 this.a); 172 }, 173 174 desaturate: function(opt_desaturateFactor) { 175 var desaturateFactor; 176 if (opt_desaturateFactor !== undefined) 177 desaturateFactor = opt_desaturateFactor; 178 else 179 desaturateFactor = 1; 180 181 var hsl = this.toHSL(); 182 hsl.s = clamp01(hsl.s * (1 - desaturateFactor)); 183 return Color.fromHSL(hsl); 184 }, 185 186 withAlpha: function(a) { 187 return new Color(this.r, this.g, this.b, a); 188 }, 189 190 toString: function() { 191 if (this.a !== undefined) { 192 return 'rgba(' + 193 this.r + ',' + this.g + ',' + 194 this.b + ',' + this.a + ')'; 195 } 196 return 'rgb(' + this.r + ',' + this.g + ',' + this.b + ')'; 197 }, 198 199 /** 200 * Returns a dict {h, s, l, a} with: 201 * |h| Hue value in [0, 1]. 202 * |s| Saturation value in [0, 1]. 203 * |l| Lightness in [0, 1]. 204 * |a| Alpha in [0, 1] 205 */ 206 toHSL: function() { 207 var r = this.r / 255; 208 var g = this.g / 255; 209 var b = this.b / 255; 210 211 var max = Math.max(r, g, b); 212 var min = Math.min(r, g, b); 213 214 var h, s; 215 var l = (max + min) / 2; 216 if (min === max) { 217 h = 0; 218 s = 0; 219 } else { 220 var delta = max - min; 221 if (l > 0.5) 222 s = delta / (2 - max - min); 223 else 224 s = delta / (max + min); 225 226 if (r === max) { 227 h = (g - b) / delta; 228 if (g < b) 229 h += 6; 230 } else if (g === max) { 231 h = 2 + ((b - r) / delta); 232 } else { 233 h = 4 + ((r - g) / delta); 234 } 235 h /= 6; 236 } 237 238 return {h: h, s: s, l: l, a: this.a}; 239 }, 240 241 toStringWithAlphaOverride: function(alpha) { 242 return 'rgba(' + 243 this.r + ',' + this.g + ',' + 244 this.b + ',' + alpha + ')'; 245 } 246 }; 247 248 return { 249 Color: Color 250 }; 251}); 252</script> 253