Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/chroma-js/src/scale.coffee')
-rw-r--r--node_modules/chroma-js/src/scale.coffee250
1 files changed, 250 insertions, 0 deletions
diff --git a/node_modules/chroma-js/src/scale.coffee b/node_modules/chroma-js/src/scale.coffee
new file mode 100644
index 0000000000..cef172f543
--- /dev/null
+++ b/node_modules/chroma-js/src/scale.coffee
@@ -0,0 +1,250 @@
+###
+ chroma.js
+
+ Copyright (c) 2011-2013, Gregor Aisch
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * The name Gregor Aisch may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ @source: https://github.com/gka/chroma.js
+###
+
+# minimal multi-purpose interface
+chroma.scale = (colors, positions) ->
+
+ # constructor
+
+ _mode = 'rgb'
+ _nacol = chroma '#ccc'
+ _spread = 0
+ _fixed = false
+ _domain = [0, 1]
+ _colors = []
+ _out = false
+ _pos = []
+ _min = 0
+ _max = 1
+ _correctLightness = false
+ _numClasses = 0
+ _colorCache = {}
+
+ # private methods
+
+ setColors = (colors, positions) ->
+ if not colors?
+ colors = ['#ddd', '#222']
+ if colors? and type(colors) == 'string' and chroma.brewer?[colors]?
+ colors = chroma.brewer[colors]
+ if type(colors) == 'array'
+ # make a copy of the colors
+ colors = colors.slice(0)
+ # convert to chroma classes
+ for c in [0..colors.length-1]
+ col = colors[c]
+ colors[c] = chroma(col) if type(col) == "string"
+ # auto-fill color position
+ if positions?
+ _pos = positions
+ else
+ _pos = []
+ for c in [0..colors.length-1]
+ _pos.push c/(colors.length-1)
+ resetCache()
+ _colors = colors
+
+ setDomain = (domain = []) ->
+ ###
+ # use this if you want to display a limited number of data classes
+ # possible methods are "equalinterval", "quantiles", "custom"
+ ###
+ _domain = domain
+ _min = domain[0]
+ _max = domain[domain.length-1]
+ resetCache()
+ if domain.length == 2
+ _numClasses = 0
+ else
+ _numClasses = domain.length-1
+
+ getClass = (value) ->
+ if _domain?
+ n = _domain.length-1
+ i = 0
+ while i < n and value >= _domain[i]
+ i++
+ return i-1
+ return 0
+
+ tmap = (t) -> t
+
+ classifyValue = (value) ->
+ val = value
+ if _domain.length > 2
+ n = _domain.length-1
+ i = getClass(value)
+ minc = _domain[0] + (_domain[1]-_domain[0]) * (0 + _spread * 0.5) # center of 1st class
+ maxc = _domain[n-1] + (_domain[n]-_domain[n-1]) * (1 - _spread * 0.5) # center of last class
+ val = _min + ((_domain[i] + (_domain[i+1] - _domain[i]) * 0.5 - minc) / (maxc-minc)) * (_max - _min)
+ val
+
+ getColor = (val, bypassMap=false) ->
+ if isNaN(val) then return _nacol
+ if not bypassMap
+ if _domain.length > 2
+ c = getClass val
+ t = c / (_numClasses-1)
+ else
+ t = f0 = if _min != _max then (val - _min) / (_max - _min) else 0
+ t = f0 = (val - _min) / (_max - _min)
+ t = Math.min(1, Math.max(0, t))
+ else
+ t = val
+
+ if not bypassMap
+ t = tmap t # lightness correction
+
+ k = Math.floor(t * 10000)
+
+ if _colorCache[k]
+ col = _colorCache[k]
+ else
+ if type(_colors) == 'array'
+ for i in [0.._pos.length-1]
+ p = _pos[i]
+ if t <= p
+ col = _colors[i]
+ break
+ if t >= p and i == _pos.length-1
+ col = _colors[i]
+ break
+ if t > p and t < _pos[i+1]
+ t = (t-p)/(_pos[i+1]-p)
+ col = chroma.interpolate _colors[i], _colors[i+1], t, _mode
+ break
+ else if type(_colors) == 'function'
+ col = _colors t
+ _colorCache[k] = col
+ col
+
+ resetCache = () ->
+ _colorCache = {}
+
+ setColors colors, positions
+
+ # public interface
+
+ f = (v) ->
+ c = getColor v
+ if _out and c[_out] then c[_out]() else c
+
+ f.domain = (domain, classes, mode='e', key) ->
+ if not arguments.length
+ return _domain
+ if classes?
+ d = chroma.analyze domain, key
+ if classes == 0
+ domain = [d.min, d.max]
+ else
+ domain = chroma.limits d, mode, classes
+ setDomain domain
+ f
+
+ f.mode = (_m) ->
+ if not arguments.length
+ return _mode
+ _mode = _m
+ resetCache()
+ f
+
+ f.range = (colors, _pos) ->
+ setColors colors, _pos
+ f
+
+ f.out = (_o) ->
+ _out = _o
+ f
+
+ f.spread = (val) ->
+ if not arguments.length
+ return _spread
+ _spread = val
+ f
+
+ f.correctLightness = (v) ->
+ if not arguments.length
+ return _correctLightness
+ _correctLightness = v
+ resetCache()
+ if _correctLightness
+ tmap = (t) ->
+ L0 = getColor(0, true).lab()[0]
+ L1 = getColor(1, true).lab()[0]
+ pol = L0 > L1
+ L_actual = getColor(t, true).lab()[0]
+ L_ideal = L0 + (L1 - L0) * t
+ L_diff = L_actual - L_ideal
+ t0 = 0
+ t1 = 1
+ max_iter = 20
+ while Math.abs(L_diff) > 1e-2 and max_iter-- > 0
+ do () ->
+ L_diff *= -1 if pol
+ if L_diff < 0
+ t0 = t
+ t += (t1 - t) * 0.5
+ else
+ t1 = t
+ t += (t0 - t) * 0.5
+ L_actual = getColor(t, true).lab()[0]
+ L_diff = L_actual - L_ideal
+ t
+ else
+ tmap = (t) -> t
+ f
+
+ f.colors = (out='hex') ->
+ # returns all colors based on the defined classes
+ colors = []
+ samples = []
+ if _domain.length > 2
+ for i in [1..._domain.length]
+ samples.push (_domain[i-1]+_domain[i])*0.5
+ else
+ samples = _domain
+ for i in samples
+ colors.push f(i)[out]()
+ colors
+
+ f
+
+# some pre-defined color scales:
+chroma.scales ?= {}
+
+chroma.scales.cool = ->
+ chroma.scale [chroma.hsl(180,1,.9), chroma.hsl(250,.7,.4)]
+
+chroma.scales.hot = ->
+ chroma.scale(['#000','#f00','#ff0','#fff'], [0,.25,.75,1]).mode('rgb')
+