| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #import('dart:html'); | |
| 6 | |
| 7 class Color { | |
| 8 int hue; | |
| 9 double saturation; | |
| 10 double lightness; | |
| 11 | |
| 12 Color(int this.hue, double this.saturation, double this.lightness); | |
| 13 | |
| 14 factory Color.rgb(double red, double green, double blue) { | |
| 15 final r = red; | |
| 16 final g = green; | |
| 17 final b = blue; | |
| 18 final max = Math.max(Math.max(r, g), b); | |
| 19 final min = Math.min(Math.min(r, g), b); | |
| 20 final d = max - min; | |
| 21 | |
| 22 double h; | |
| 23 if (max == min) { | |
| 24 h = 0.0; | |
| 25 } else if (max == r) { | |
| 26 h = 60 * (g-b)/d; | |
| 27 } else if (max == g) { | |
| 28 h = 60 * (b-r)/d + 120; | |
| 29 } else { // max == b | |
| 30 h = 60 * (r - g)/d + 240; | |
| 31 } | |
| 32 | |
| 33 final l = (max + min)/2; | |
| 34 | |
| 35 double s; | |
| 36 if (max == min) { | |
| 37 s = 0.0; | |
| 38 } else if (l < 0.5) { | |
| 39 s = d/(2*l); | |
| 40 } else { | |
| 41 s = d/(2 - 2*l); | |
| 42 } | |
| 43 | |
| 44 return new Color((h.round() % 360).toInt(), s, l); | |
| 45 } | |
| 46 | |
| 47 factory Color.hex(String hex) => new Color.rgb( | |
| 48 _parseHex(hex.substring(1, 3))/255, | |
| 49 _parseHex(hex.substring(3, 5))/255, | |
| 50 _parseHex(hex.substring(5, 7))/255); | |
| 51 | |
| 52 // This should be in the core library. Issue #233 | |
| 53 static int _parseHex(String hex) { | |
| 54 final codes = hex.charCodes(); | |
| 55 var number = 0; | |
| 56 for (var i = 0; i < codes.length; i++) { | |
| 57 final code = codes[i]; | |
| 58 var digit; | |
| 59 if (code >= 48 && code <= 57) { // 0-9 | |
| 60 digit = code - 48; | |
| 61 } else if (code >= 97 && code <= 102) { // a-f | |
| 62 digit = code - 97 + 10; | |
| 63 } else { | |
| 64 throw "Invalid hex string: '$hex'"; | |
| 65 } | |
| 66 number *= 16; // shift previous digits left one place | |
| 67 number += digit; | |
| 68 } | |
| 69 return number; | |
| 70 } | |
| 71 | |
| 72 String get hex() { | |
| 73 final h = (hue % 360) / 360; | |
| 74 final s = saturation; | |
| 75 final l = lightness; | |
| 76 | |
| 77 // HSL to RGB algorithm from the CSS spec | |
| 78 // http://www.w3.org/TR/css3-color/#hsl-color | |
| 79 final m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; | |
| 80 final m1 = l * 2 - m2; | |
| 81 final r = _hueToRgb(m1, m2, h + 1/3); | |
| 82 final g = _hueToRgb(m1, m2, h); | |
| 83 final b = _hueToRgb(m1, m2, h - 1/3); | |
| 84 | |
| 85 return '#${_hexPair(r)}${_hexPair(g)}${_hexPair(b)}'; | |
| 86 } | |
| 87 | |
| 88 Color dup() => new Color(hue, saturation, lightness); | |
| 89 | |
| 90 double _hueToRgb(double m1, double m2, double h) { | |
| 91 if (h < 0) h++; | |
| 92 if (h > 1) h--; | |
| 93 if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; | |
| 94 if (h * 2 < 1) return m2; | |
| 95 if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; | |
| 96 return m1; | |
| 97 } | |
| 98 | |
| 99 String _hexPair(double color) { | |
| 100 assert(color >= 0 && color <= 1); | |
| 101 final str = (color * 0xff).round().toRadixString(16); | |
| 102 return str.length == 1 ? '0$str' : str;; | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 SVGSVGElement logo; | |
| 107 InputElement hue, saturation, lightness; | |
| 108 Map<String, Color> defaultColors; | |
| 109 | |
| 110 onSliderChange(_) { | |
| 111 final hueDelta = Math.parseInt(hue.value) - 180; | |
| 112 final saturationMod = Math.parseInt(saturation.value)/100; | |
| 113 final lightnessMod = Math.parseInt(lightness.value)/100; | |
| 114 | |
| 115 logo.queryAll("path").forEach((p) { | |
| 116 final color = defaultColors[p.id].dup(); | |
| 117 color.hue += hueDelta; | |
| 118 | |
| 119 if (saturationMod > 0) { | |
| 120 color.saturation += saturationMod * (1 - color.saturation); | |
| 121 } else { | |
| 122 color.saturation += saturationMod * color.saturation; | |
| 123 } | |
| 124 | |
| 125 if (lightnessMod > 0) { | |
| 126 color.lightness += lightnessMod * (1 - color.lightness); | |
| 127 } else { | |
| 128 color.lightness += lightnessMod * color.lightness; | |
| 129 } | |
| 130 | |
| 131 p.style.setProperty('fill', color.hex); | |
| 132 }); | |
| 133 } | |
| 134 | |
| 135 void main() { | |
| 136 defaultColors = {}; | |
| 137 | |
| 138 window.on.contentLoaded.add((_) { | |
| 139 logo = new SVGElement.svg(""" | |
| 140 <svg xmlns="http://www.w3.org/2000/svg" | |
| 141 version="1.1" | |
| 142 width="371.6655" | |
| 143 height="374.14087"> | |
| 144 <filter id="inverse"> | |
| 145 <feComponentTransfer> | |
| 146 <feFuncR type="table" tableValues="1 0"/> | |
| 147 <feFuncG type="table" tableValues="1 0"/> | |
| 148 <feFuncB type="table" tableValues="1 0"/> | |
| 149 </feComponentTransfer> | |
| 150 </filter> | |
| 151 <path | |
| 152 d="m 101.86949,101.86487 -24.192001,-24.192004 0.088,174.807994 0.296,8.164
c 0.12,3.848 0.84,8.18 2.012,12.684 l 191.615991,67.55601 47.89201,-21.216 0.01
6,-0.056 -217.728,-217.748 z" | |
| 153 id="path2900" | |
| 154 style="fill: #31beb2" /> | |
| 155 <path | |
| 156 d="m 80.073489,273.32486 0.02,0.008 c -0.02,-0.084 -0.052,-0.168 -0.076,-0.
252 0.028,0.084 0.036,0.16 0.056,0.244 z m 239.524001,46.28401 m -0.016,0.056 -4
7.89201,21.216 -191.591991,-67.54801 c 3.656,14.044 11.764,29.83201 20.476001,38
.45601 l 62.52,62.172 139.052,0.18 17.452,-54.532 -0.016,0.056 z" | |
| 157 id="path2902" | |
| 158 style="fill: #75ccc3" /> | |
| 159 <path | |
| 160 d="M 77.673489,77.668866 3.1974828,190.16487 c -6.192,6.616 -3.11599997,20.
244 6.8520002,30.276 l 42.996005,43.35199 27.028001,9.528 c -1.172,-4.504 -1.892
,-8.832 -2.012,-12.684 l -0.296,-8.164 -0.092,-174.803994 0,0 z" | |
| 161 id="path2904" | |
| 162 style="fill: #008bc9" /> | |
| 163 <path | |
| 164 d="m 273.26148,79.920866 c -4.48,-1.148 -8.808,-1.856 -12.708,-1.98 l -8.64
,-0.308 -174.239991,0.036 241.960001,241.940004 0.02,-0.008 21.24,-47.93601 -67.
63201,-191.743994 z" | |
| 165 id="path2906" | |
| 166 style="fill: #0082c4" /> | |
| 167 <path | |
| 168 d="m 273.04948,79.876866 c 0.072,0.02 0.148,0.044 0.22,0.064 l -0.004,-0.02
c -0.076,-0.02 -0.144,-0.024 -0.216,-0.044 z m 38.66001,20.576004 c -8.792,-8.8
60004 -24.37601,-16.912004 -38.44001,-20.512004 l 67.62801,191.727994 -21.24,47.
93601 -0.02,0.008 51.928,-16.592 0.1,-142.368 -59.956,-60.2 z" | |
| 169 id="path2908" | |
| 170 style="fill: #008bc9" /> | |
| 171 <path | |
| 172 d="M 263.78548,53.048866 220.45349,10.028873 c -10.02,-9.92799955 -23.664,-
13.0239996 -30.26,-6.8439996 L 77.677489,77.672866 l 174.239991,-0.036 8.64,0.30
8 c 3.9,0.124 8.228,0.832 12.708,1.98 l -9.48,-26.876 z m -186.111991,24.62" | |
| 173 id="path2910" | |
| 174 style="fill: #75ccc3" /> | |
| 175 </svg> | |
| 176 """); | |
| 177 | |
| 178 document.query("#icon").elements.add(logo); | |
| 179 logo.queryAll("path").forEach((p) { | |
| 180 defaultColors[p.id] = new Color.hex(p.style.getPropertyValue('fill')); | |
| 181 }); | |
| 182 | |
| 183 hue = document.query("input[name=hue]"); | |
| 184 hue.on.change.add(onSliderChange); | |
| 185 saturation = document.query("input[name=saturation]"); | |
| 186 saturation.on.change.add(onSliderChange); | |
| 187 lightness = document.query("input[name=lightness]"); | |
| 188 lightness.on.change.add(onSliderChange); | |
| 189 | |
| 190 document.query("input[name=invert]").on.change.add((Event e) { | |
| 191 InputElement invert = e.target; | |
| 192 if (invert.checked) { | |
| 193 logo.classes = ['inverse']; | |
| 194 } else { | |
| 195 logo.classes = []; | |
| 196 } | |
| 197 }); | |
| 198 }); | |
| 199 } | |
| OLD | NEW |