diff options
author | Rom Grk <romgrk.cc@gmail.com> | 2020-10-18 04:56:05 -0400 |
---|---|---|
committer | Rom Grk <romgrk.cc@gmail.com> | 2020-10-18 04:56:05 -0400 |
commit | 8cd705e800db80e96e3109cb2b9e5d0749f98675 (patch) | |
tree | b101f9f37c1f94c5182832c47df0a8ae536ad35d /autoload |
initial commit
Diffstat (limited to 'autoload')
-rw-r--r-- | autoload/color.vim | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/autoload/color.vim b/autoload/color.vim new file mode 100644 index 0000000..b5e0e8f --- /dev/null +++ b/autoload/color.vim @@ -0,0 +1,269 @@ +" File: color.vim +" Author: romgrk +" Date: 15 Mar 2016 +" Description: vimscript RGB/HSL color parsing +" This is mostly a transcript from a javascript color parsing module. +" !::exe [so %] +" ================================================================================ +" Definitions: {{{1 +" In function names: +" • “Hex” refers to hexadecimal color format e.g. #599eff +" • “RGB” refers to an array of numbers [r, g, b] +" where r,g,b ∈ [0, 255] +" • “HSL” refers to an array of floats [h, s, l] +" where h,s,l ∈ [0, 1.0] +" }}}1 +" ================================================================================ +" Color-format patterns: +" {{{1 + +let s:patterns = {} + +" 6 hex-numbers, optionnal #-prefix +let s:patterns['hex'] = '\v#?(\x{2})(\x{2})(\x{2})' + +" short version is strict: starting # mandatory +let s:patterns['shortHex'] = '\v#(\x{1})(\x{1})(\x{1})' + +" Disabled +"let s:patterns['rgb'] = '\vrgb\s*\((\d+)\s*,(\d+)\s*,(\d+)\s*)\s*' +"let s:patterns['rgba'] = '\vrgba\s*\((\d+)\s*,(\d+)\s*,(\d+)\s*,(\d+)\s*)\s*' + +" }}}1 +" ================================================================================ +" Functions: +" {{{1 + +" @params String string The string to test +" @returns Boolean [0 or 1] if string matches: rrggbb OR #rrggbb OR #rgb +fu! color#Test (string) + for key in keys(s:patterns) + if a:string =~# s:patterns[key] + return 1 + end + endfor + return 0 +endfu + +" @params (r, g, b) +" @params ([r, g, b]) +" @returns String A RGB color +fu! color#RGBtoHex (...) + let [r, g, b] = ( a:0==1 ? a:1 : a:000 ) + let num = printf('%02x', float2nr(r)) . '' + \ . printf('%02x', float2nr(g)) . '' + \ . printf('%02x', float2nr(b)) . '' + return '#' . num +endfu + +" @param {String|Number} color The color to parse +fu! color#HexToRGB (color) + if type(a:color) == 2 + let color = printf('%x', a:color) + else + let color = a:color | end + + let matches = matchlist(color, s:patterns['hex']) + let factor = 0x1 + + if empty(matches) + let matches = matchlist(color, s:patterns['shortHex']) + let factor = 0x10 + end + + if len(matches) < 4 + throw 'Couldnt parse ' . string(color) . ' ' . string(matches) + end + + let r = str2nr(matches[1], 16) * factor + let g = str2nr(matches[2], 16) * factor + let b = str2nr(matches[3], 16) * factor + + return [r, g, b] +endfu + + +" Converts an HSL color value to RGB. Conversion formula +" adapted from http://en.wikipedia.org/wiki/HSL_color_space. +" Assumes h, s, and l are contained in the set [0, 1] and +" returns r, g, and b in the set [0, 255]. +" @param Number h OR @param Array [h, s, l] +" @param Number s +" @param Number l +" @returns Array [r, g, b] The RGB representation +fu! color#HSLtoRGB(...) " (h, s, l) + let [h, s, l] = ( a:0==1 ? a:1 : a:000 ) + + if (s == 0.0) " achromatic + let r = l + let g = l + let b = l + else + let q = l < 0.5 ? l * (1 + s) : l + s - l * s + let p = 2 * l - q + let r = color#Hue2RGB(p, q, h + 0.33333) + let g = color#Hue2RGB(p, q, h) + let b = color#Hue2RGB(p, q, h - 0.33333) + end + + return [r * 255.0, g * 255.0, b * 255.0] +endfu + + +" @param Number r OR @param Array [r, g, b] +" @param Number g +" @param Number b +" @returns Array [h, s, l] The HSL representation +fu! color#RGBtoHSL(...) + let [r, g, b] = ( a:0==1 ? a:1 : a:000 ) + let max = max([r, g, b]) + let min = min([r, g, b]) + + let r = str2float(r) + let g = str2float(g) + let b = str2float(b) + let max = str2float(max) + let min = str2float(min) + + let max = max / 255 + let min = min / 255 + let r = r / 255 + let g = g / 255 + let b = b / 255 + let h = str2float(0) + let s = str2float(0) + let l = (max + min) / 2 + + if (max == min) + let h = 0 " achromatic + let s = 0 " achromatic + else + let d = max - min + let s = (l > 0.5 ? d / (2 - max - min) + \ : d / (max + min) ) + if (max == r) + let h = (g - b) / d + (g < b ? 6 : 0) + end + if (max == g) + let h = (b - r) / d + 2 + end + if (max == b) + let h = (r - g) / d + 4 + end + let h = h / 6 + end + + return [h, s, l] +endfu + +fu! color#Hue2RGB(...) " (p, q, t) + let [p, q, t] = ( a:0==1 ? a:1 : a:000 ) + + if(t < 0) | let t += 1 | end + if(t > 1) | let t -= 1 | end + + if(t < 1.0/6) | return (p + (q - p) * 6.0 * t) | end + if(t < 1.0/2) | return (q) | end + if(t < 2.0/3) | return (p + (q - p) * (2.0/3 - t) * 6.0) | end + + return p +endfu + +" }}}1 +" ================================================================================ +" Composed functions: +" {{{1 + +fu! color#HexToHSL (color) + let [r, g, b] = color#HexToRGB(a:color) + return color#RGBtoHSL(r, g, b) +endfu + +fu! color#HSLtoHex (...) + let [h, s, l] = ( a:0==1 ? a:1 : a:000 ) + let [r, g, b] = color#HSLtoRGB(h, s, l) + return color#RGBtoHex(r, g, b) +endfu + +" @params String color The color +" @params {Number|String|Float} [amount=5] The percentage of light +fu! color#Lighten(color, ...) + let amount = a:0 ? + \(type(a:1) < 2 ? + \str2float(a:1) : a:1 ) + \: 5.0 + + if(amount < 1.0) + let amount = 1.0 + amount + else + let amount = 1.0 + (amount / 100.0) + end + + let rgb = color#HexToRGB(a:color) + let rgb = map(rgb, 'v:val * amount') + let rgb = map(rgb, 'v:val > 255.0 ? 255.0 : v:val') + let rgb = map(rgb, 'float2nr(v:val)') + let hex = color#RGBtoHex(rgb) + return hex +endfu + +" @params String color The color +" @params {Number|String|Float} [amount=5] The percentage of darkness +fu! color#Darken(color, ...) + let amount = a:0 ? + \(type(a:1) < 2 ? + \str2float(a:1) : a:1 ) + \: 5.0 + + if(amount < 1.0) + let amount = 1.0 - amount + else + let amount = 1.0 - (amount / 100.0) + end + + if(amount < 0.0) + let amount = 0.0 | end + + + let rgb = color#HexToRGB(a:color) + let rgb = map(rgb, 'v:val * amount') + let rgb = map(rgb, 'v:val > 255.0 ? 255.0 : v:val') + let rgb = map(rgb, 'float2nr(v:val)') + let hex = color#RGBtoHex(rgb) + return hex +endfu + +function! color#Decrease (...) + if &background == 'light' + return call(function('color#Lighten'), a:000) + end + return call(function('color#Darken'), a:000) +endfunc + +function! color#Increase (...) + if &background == 'light' + return call(function('color#Darken'), a:000) + end + return call(function('color#Lighten'), a:000) +endfunc + +function! color#Mix (a, b, ...) + let amount = a:0 ? a:1 : 0.5 + + let ca = color#HexToRGB(a:a) + let cb = color#HexToRGB(a:b) + + let r = s:interpolate(ca[0], cb[0], amount) + let g = s:interpolate(ca[1], cb[1], amount) + let b = s:interpolate(ca[2], cb[2], amount) + + return color#RGBtoHex([r, g, b]) +endfunc + +function! s:interpolate (start, end, amount) + let diff = a:end - a:start + return a:start + (diff * a:amount) +endfunc + +" }}}1 + |