chroma 0.0.1.alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 58cd2ee5df8643fe579d9f3abbb73eb6e5abdd7e
4
+ data.tar.gz: 9f7fc61bf911705268bf1ad174c68106db3e8184
5
+ SHA512:
6
+ metadata.gz: fc91d84ce91dd630d8d8c5371d83e092e11748b44b6158a4281dde2246ced584fc8bd6e30f63f6a5acc12779cde30eb0892c88cb6825b38d05f4da20d55a95e7
7
+ data.tar.gz: e61fd039b71428b30d286d4294bef7c116efad95991dce5174fa1c0ae771da9981119b231756971f0473775d2085957ca83b5347d4e3d98ddf6a9de4a81a458d
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in colortastic.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2015, Jeremy Fairbank <elpapapollo@gmail.com>
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Chroma
2
+
3
+ Chroma is a color manipulation and palette generation library. It is heavily
4
+ inspired by and a very close Ruby port of the
5
+ [tinycolor.js](https://bgrins.github.io/TinyColor/)
6
+ library. Many thanks to [Brian Grinstead](http://www.briangrinstead.com/blog/)
7
+ for his hard work on that library.
8
+
9
+ Chroma is in alpha stage at the moment. Most of the API methods from tinycolor
10
+ have been ported over with a few exceptions. However, I will be working on
11
+ cleaning up the API where needed, adding docs and examples, and adding tests
12
+ before a first release. Because this is currently in alpha, please be
13
+ prepared for possible API changes or bugs.
14
+
15
+ Please don't hesitate to examine the code and make issues or pull requests
16
+ where you feel it is necessary. Please refer to the
17
+ [Contributing](#contributing) section below.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'chroma', '0.0.1.alpha.1'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ Or install it yourself as:
32
+
33
+ $ gem install chroma
34
+
35
+ ## Usage
36
+
37
+ Chroma adds several of the methods available in
38
+ [tinycolor.js](https://github.com/bgrins/TinyColor) but renamed appropriately
39
+ for Ruby conventions (i.e. `isDark` becomes `dark?`).
40
+
41
+ To create a color, just call the `Chroma.paint` method, passing in a string
42
+ that represents a color.
43
+
44
+ ```ruby
45
+ Chroma.paint 'red' # named colors
46
+ Chroma.paint '#00ff00' # 6 character hexadecimal
47
+ Chroma.paint '#00f' # 3 character hexadecimal
48
+ Chroma.paint 'rgb(255, 255, 0)' # rgb
49
+ Chroma.paint 'rgba(255, 255, 0, 0.5)' # rgba
50
+ Chroma.paint 'hsl(60, 100%, 50%)' # hsl with percentages
51
+ Chroma.paint 'hsl(60, 1, 0.5)' # hsl with decimals
52
+ Chroma.paint 'hsv(60, 100%, 50%)' # hsv with percentages
53
+ Chroma.paint 'hsv(60, 1, 0.5)' # hsv with decimals
54
+ ```
55
+
56
+ To work directly from a string you can also use the `String#paint` method:
57
+
58
+ ```ruby
59
+ 'red'.paint
60
+ '#00f'.paint
61
+ 'rgb(255, 255, 0)'.paint
62
+
63
+ # etc...
64
+ ```
65
+
66
+ ## Contributing
67
+
68
+ Please branch from **dev** for all pull requests.
69
+
70
+ 1. Fork it (https://github.com/jfairbank/chroma/fork)
71
+ 2. Checkout dev (`git checkout dev`)
72
+ 3. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 5. Push to the branch (`git push origin my-new-feature`)
75
+ 6. Create a new pull request against dev
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/chroma.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'chroma/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'chroma'
8
+ spec.version = Chroma::VERSION
9
+ spec.authors = ['Jeremy Fairbank']
10
+ spec.email = ['elpapapollo@gmail.com']
11
+ spec.summary = %q{Color manipulation and palette generation.}
12
+ spec.description = %q{Chroma is a color manipulation and palette generation gem.}
13
+ spec.homepage = 'https://github.com/jfairbank/chroma'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ end
data/lib/chroma.rb ADDED
@@ -0,0 +1,63 @@
1
+ # General
2
+ require 'chroma/version'
3
+ require 'yaml'
4
+
5
+ # Modules
6
+ require 'chroma/helpers/bounders'
7
+
8
+ # Color
9
+ require 'chroma/color/attributes'
10
+ require 'chroma/color/serializers'
11
+ require 'chroma/color/modifiers'
12
+ require 'chroma/color'
13
+ require 'chroma/color_modes'
14
+
15
+ # Palettes
16
+ require 'chroma/harmonies'
17
+
18
+ # RGB Generators
19
+ require 'chroma/rgb_generator'
20
+ require 'chroma/rgb_generator/base'
21
+ require 'chroma/rgb_generator/from_string'
22
+ require 'chroma/rgb_generator/from_rgb_values'
23
+ require 'chroma/rgb_generator/from_rgb'
24
+ require 'chroma/rgb_generator/from_hsl_values'
25
+ require 'chroma/rgb_generator/from_hsl'
26
+ require 'chroma/rgb_generator/from_hsv_values'
27
+ require 'chroma/rgb_generator/from_hsv'
28
+ require 'chroma/rgb_generator/from_hex_string_values'
29
+
30
+ # Converters
31
+ require 'chroma/converters/base'
32
+ require 'chroma/converters/rgb_converter'
33
+ require 'chroma/converters/hsl_converter'
34
+ require 'chroma/converters/hsv_converter'
35
+
36
+ # Extensions
37
+ require 'chroma/extensions/string'
38
+
39
+ module Chroma
40
+ class << self
41
+ def paint(input)
42
+ Color.new(input)
43
+ end
44
+
45
+ def hex_from_name(name)
46
+ named_colors_map[name]
47
+ end
48
+
49
+ def name_from_hex(hex)
50
+ hex_named_colors_map[hex]
51
+ end
52
+
53
+ private
54
+
55
+ def hex_named_colors_map
56
+ @hex_named_colors_map ||= named_colors_map.invert
57
+ end
58
+
59
+ def named_colors_map
60
+ @named_colors ||= YAML.load_file(File.expand_path('../support/named_colors.yml', __FILE__))
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,34 @@
1
+ module Chroma
2
+ class Color
3
+ include Attributes
4
+ include Serializers
5
+ include Modifiers
6
+ include Helpers::Bounders
7
+
8
+ def initialize(input, format = nil)
9
+ @input = input
10
+ @rgb, gen_format = generate_rgb_and_format(input)
11
+ @format = format || gen_format
12
+ end
13
+
14
+ def complement
15
+ hsl = to_hsl
16
+ hsl.h = (hsl.h + 180) % 360
17
+ Color.new(hsl)
18
+ end
19
+
20
+ def palette
21
+ Harmonies.new(self)
22
+ end
23
+
24
+ private
25
+
26
+ def to_2char_hex(n)
27
+ n.round.to_s(16).rjust(2, '0')
28
+ end
29
+
30
+ def generate_rgb_and_format(input)
31
+ RgbGenerator.generate_rgb_and_format(input)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ module Chroma
2
+ class Color
3
+ module Attributes
4
+ def dark?
5
+ brightness < 128
6
+ end
7
+
8
+ def light?
9
+ !dark?
10
+ end
11
+
12
+ def alpha
13
+ @rgb.a
14
+ end
15
+
16
+ def brightness
17
+ (@rgb.r * 299 + @rgb.g * 587 + @rgb.b * 114) / 1000.0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,52 @@
1
+ module Chroma
2
+ class Color
3
+ module Modifiers
4
+ def lighten(amount = 10)
5
+ hsl = to_hsl
6
+ hsl.l = clamp01(hsl.l + amount / 100.0)
7
+ self.class.new(hsl, @format)
8
+ end
9
+
10
+ def brighten(amount = 10)
11
+ # Don't include alpha
12
+ rgb = @rgb.to_a[0..2].map(&:round)
13
+ amount = (255 * (-amount / 100.0)).round
14
+
15
+ rgb.map! do |n|
16
+ [0, [255, n - amount].min].max
17
+ end
18
+
19
+ self.class.new(ColorModes::Rgb.new(*rgb), @format)
20
+ end
21
+
22
+ def darken(amount = 10)
23
+ hsl = to_hsl
24
+ hsl.l = clamp01(hsl.l - amount / 100.0)
25
+ self.class.new(hsl, @format)
26
+ end
27
+
28
+ def desaturate(amount = 10)
29
+ hsl = to_hsl
30
+ hsl.s = clamp01(hsl.s - amount / 100.0)
31
+ self.class.new(hsl, @format)
32
+ end
33
+
34
+ def saturate(amount = 10)
35
+ hsl = to_hsl
36
+ hsl.s = clamp01(hsl.s + amount / 100.0)
37
+ self.class.new(hsl, @format)
38
+ end
39
+
40
+ def greyscale
41
+ desaturate(100)
42
+ end
43
+
44
+ def spin(amount)
45
+ hsl = to_hsl
46
+ hue = (hsl.h.round + amount) % 360
47
+ hsl.h = hue < 0 ? 360 + hue : hue
48
+ self.class.new(hsl, @format)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,113 @@
1
+ module Chroma
2
+ class Color
3
+ module Serializers
4
+ def to_hsv
5
+ Converters::HsvConverter.convert_rgb(@rgb)
6
+ end
7
+
8
+ def to_hsv_s
9
+ to_hs_s(:v)
10
+ end
11
+
12
+ def to_hsl
13
+ Converters::HslConverter.convert_rgb(@rgb)
14
+ end
15
+
16
+ def to_hsl_s
17
+ to_hs_s(:l)
18
+ end
19
+
20
+ def to_hex(allow_3 = false)
21
+ r, g, b = [@rgb.r, @rgb.g, @rgb.b].map do |n|
22
+ to_2char_hex(n)
23
+ end
24
+
25
+ if allow_3 && r[0] == r[1] && g[0] == g[1] && b[0] == b[1]
26
+ return "#{r[0]}#{g[0]}#{b[0]}"
27
+ end
28
+
29
+ [r, g, b].flatten * ''
30
+ end
31
+
32
+ def to_hex_s(allow_3 = false)
33
+ "##{to_hex(allow_3)}"
34
+ end
35
+
36
+ def to_hex8
37
+ [
38
+ to_2char_hex(alpha * 255),
39
+ to_2char_hex(@rgb.r),
40
+ to_2char_hex(@rgb.g),
41
+ to_2char_hex(@rgb.b)
42
+ ].join('')
43
+ end
44
+
45
+ def to_hex8_s
46
+ "##{to_hex8}"
47
+ end
48
+
49
+ def to_rgb
50
+ @rgb
51
+ end
52
+
53
+ def to_rgb_s
54
+ middle = @rgb.to_a[0..2].map(&:round).join(', ')
55
+
56
+ to_alpha_s(:rgb, middle)
57
+ end
58
+
59
+ def to_name
60
+ return 'transparent' if alpha.zero?
61
+
62
+ if alpha < 1 || (name = Chroma.name_from_hex(to_hex(true))).nil?
63
+ '<unknown>'
64
+ else
65
+ name
66
+ end
67
+ end
68
+
69
+ alias_method :to_name_s, :to_name
70
+
71
+ def to_s(format = @format)
72
+ use_alpha = alpha < 1 && alpha >= 0 && /^hex(3|6)?/ =~ format
73
+
74
+ return to_rgb_s if use_alpha
75
+
76
+ case format.to_s
77
+ when 'rgb' then to_rgb_s
78
+ when 'hex', 'hex6' then to_hex_s
79
+ when 'hex3' then to_hex_s(true)
80
+ when 'hex8' then to_hex8_s
81
+ when 'hsl' then to_hsl_s
82
+ when 'hsv' then to_hsv_s
83
+ when 'name' then to_name
84
+ else to_hex_s
85
+ end
86
+ end
87
+
88
+ alias_method :inspect, :to_s
89
+
90
+ private
91
+
92
+ def to_hs_s(third)
93
+ color = send("to_hs#{third}")
94
+
95
+ h = color.h.round
96
+ s = (color.s * 100).round
97
+ lv = (color.send(third) * 100).round
98
+
99
+ middle = "#{h}, #{s}%, #{lv}%"
100
+
101
+ to_alpha_s("hs#{third}", middle)
102
+ end
103
+
104
+ def to_alpha_s(mode, middle)
105
+ if alpha < 1
106
+ "#{mode}a(#{middle}, #{alpha})"
107
+ else
108
+ "#{mode}(#{middle})"
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,29 @@
1
+ module Chroma
2
+ module ColorModes
3
+ class << self
4
+ private
5
+
6
+ def build(*attrs)
7
+ Class.new do
8
+ attr_accessor *(attrs + [:a])
9
+
10
+ class_eval <<-EOS
11
+ def initialize(#{attrs * ', '}, a = 1)
12
+ #{attrs.map{|attr| "@#{attr}"} * ', '}, @a = #{attrs * ', '}, a
13
+ end
14
+
15
+ def to_a
16
+ [#{attrs.map{|attr| "@#{attr}"} * ', '}, @a]
17
+ end
18
+
19
+ alias_method :to_ary, :to_a
20
+ EOS
21
+ end
22
+ end
23
+ end
24
+
25
+ Rgb = build :r, :g, :b
26
+ Hsl = build :h, :s, :l
27
+ Hsv = build :h, :s, :v
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module Chroma
2
+ module Converters
3
+ class Base
4
+ include Helpers::Bounders
5
+
6
+ def initialize(input)
7
+ @input = input
8
+ end
9
+
10
+ def self.convert_rgb(rgb)
11
+ new(rgb).convert_rgb
12
+ end
13
+
14
+ def self.convert_hsl(hsl)
15
+ new(hsl).convert_hsl
16
+ end
17
+
18
+ def self.convert_hsv(hsv)
19
+ new(hsv).convert_hsv
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ module Chroma
2
+ module Converters
3
+ class HslConverter < Base
4
+ def convert_rgb
5
+ r = bound01(@input.r, 255)
6
+ g = bound01(@input.g, 255)
7
+ b = bound01(@input.b, 255)
8
+
9
+ rgb_array = [r, g, b]
10
+
11
+ max = rgb_array.max
12
+ min = rgb_array.min
13
+ l = (max + min) * 0.5
14
+
15
+ if max == min
16
+ h = s = 0
17
+ else
18
+ d = (max - min).to_f
19
+
20
+ s = if l > 0.5
21
+ d / (2 - max - min)
22
+ else
23
+ d / (max + min)
24
+ end
25
+
26
+ h = case max
27
+ when r then (g - b) / d + (g < b ? 6 : 0)
28
+ when g then (b - r) / d + 2
29
+ when b then (r - g) / d + 4
30
+ end
31
+
32
+ h /= 6.0
33
+ end
34
+
35
+ ColorModes::Hsl.new(h * 360, s, l, @input.a)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ module Chroma
2
+ module Converters
3
+ class HsvConverter < Base
4
+ def convert_rgb
5
+ r = bound01(@input.r, 255)
6
+ g = bound01(@input.g, 255)
7
+ b = bound01(@input.b, 255)
8
+
9
+ rgb_array = [r, g, b]
10
+
11
+ max = rgb_array.max
12
+ min = rgb_array.min
13
+ v = max
14
+ d = (max - min).to_f
15
+ s = max.zero? ? 0 : d / max
16
+
17
+ if max == min
18
+ h = 0
19
+ else
20
+ h = case max
21
+ when r then (g - b) / d + (g < b ? 6 : 0)
22
+ when g then (b - r) / d + 2
23
+ when b then (r - g) / d + 4
24
+ end
25
+
26
+ h /= 6.0
27
+ end
28
+
29
+ ColorModes::Hsv.new(h * 360, s, v, @input.a)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,60 @@
1
+ module Chroma
2
+ module Converters
3
+ class RgbConverter < Base
4
+ def convert_hsl
5
+ h, s, l = @input
6
+
7
+ h = bound01(h, 360)
8
+ s = bound01(s, 100)
9
+ l = bound01(l, 100)
10
+
11
+ if s.zero?
12
+ r = g = b = l * 255
13
+ else
14
+ q = l < 0.5 ? l * (1 + s) : l + s - l * s
15
+ p = 2 * l - q
16
+ r = hue_to_rgb(p, q, h + 1/3.0) * 255
17
+ g = hue_to_rgb(p, q, h) * 255
18
+ b = hue_to_rgb(p, q, h - 1/3.0) * 255
19
+ end
20
+
21
+ ColorModes::Rgb.new(r, g, b)
22
+ end
23
+
24
+ def convert_hsv
25
+ h, s, v = @input
26
+
27
+ h = bound01(h, 360) * 6
28
+ s = bound01(s, 100)
29
+ v = bound01(v, 100)
30
+
31
+ i = h.floor
32
+ f = h - i
33
+ p = v * (1 - s)
34
+ q = v * (1 - f * s)
35
+ t = v * (1 - (1 - f) * s)
36
+ mod = i % 6
37
+
38
+ r = [v, q, p, p, t, v][mod] * 255
39
+ g = [t, v, v, q, p, p][mod] * 255
40
+ b = [p, p, t, v, v, q][mod] * 255
41
+
42
+ ColorModes::Rgb.new(r, g, b)
43
+ end
44
+
45
+ private
46
+
47
+ def hue_to_rgb(p, q, t)
48
+ if t < 0 then t += 1
49
+ elsif t > 1 then t -= 1
50
+ end
51
+
52
+ if t < 1/6.0 then p + (q - p) * 6 * t
53
+ elsif t < 0.5 then q
54
+ elsif t < 2/3.0 then p + (q - p) * (2/3.0 - t) * 6
55
+ else p
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def paint
3
+ Chroma.paint(self)
4
+ end
5
+ end
@@ -0,0 +1,55 @@
1
+ module Chroma
2
+ class Harmonies
3
+ def initialize(color)
4
+ @color = color
5
+ end
6
+
7
+ def complement
8
+ [@color, @color.complement]
9
+ end
10
+
11
+ def triad
12
+ hsl_map([0, 120, 240])
13
+ end
14
+
15
+ def tetrad
16
+ hsl_map([0, 90, 180, 270])
17
+ end
18
+
19
+ def split_complement
20
+ hsl_map([0, 72, 216])
21
+ end
22
+
23
+ def analogous(results = 6, slices = 30)
24
+ hsl = @color.to_hsl
25
+ part = 360 / slices
26
+ hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360
27
+
28
+ (results - 1).times.reduce([@color]) do |arr, n|
29
+ hsl.h = (hsl.h + part) % 360
30
+ arr << Color.new(hsl)
31
+ end
32
+ end
33
+
34
+ def monochromatic(results = 6)
35
+ h, s, v = @color.to_hsv
36
+ modification = 1.0 / results
37
+
38
+ results.times.map do
39
+ Color.new(ColorModes::Hsv.new(h, s, v)).tap do
40
+ v = (v + modification) % 1
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def hsl_map(degrees)
48
+ h, s, l = @color.to_hsl
49
+
50
+ degrees.map do |deg|
51
+ Color.new(ColorModes::Hsl.new((h + deg) % 360, s, l))
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ module Chroma
2
+ module Helpers
3
+ module Bounders
4
+ def bound01(n, max)
5
+ is_percent = n.to_s.include? '%'
6
+ n = [max, [0, n.to_f].max].min
7
+ n = (n * max).to_i / 100 if is_percent
8
+
9
+ return 1 if (n - max).abs < 0.000001
10
+
11
+ (n % max) / max.to_f
12
+ end
13
+
14
+ def bound_alpha(a)
15
+ a = a.to_f
16
+ a = 1 if a < 0 || a > 1
17
+ a
18
+ end
19
+
20
+ def clamp01(n)
21
+ [1, [0, n].max].min
22
+ end
23
+
24
+ def to_percentage(n)
25
+ n = n.to_f
26
+ n = "#{n * 100}%" if n <= 1
27
+ n
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class << self
4
+ def generate_rgb_and_format(input)
5
+ get_generator(input).generate.tap do |(rgb)|
6
+ rgb.r = round(rgb.r)
7
+ rgb.g = round(rgb.g)
8
+ rgb.b = round(rgb.b)
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def get_generator(input)
15
+ klass = case input
16
+ when String then FromString
17
+ when ColorModes::Hsl then FromHsl
18
+ when ColorModes::Hsv then FromHsv
19
+ when ColorModes::Rgb then FromRgb
20
+ end
21
+
22
+ klass.new(input)
23
+ end
24
+
25
+ def round(n)
26
+ if n < 1
27
+ n.round
28
+ else
29
+ #(n * 100).round / 100
30
+ n
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class Base
4
+ include Helpers::Bounders
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,30 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHexStringValues < Base
4
+ def initialize(format, r, g, b, a = 'ff')
5
+ @format = format || :hex
6
+ @r, @g, @b, @a = r, g, b, a
7
+ end
8
+
9
+ def generate
10
+ r, g, b = [@r, @g, @b].map { |n| n.to_i(16) }
11
+ a = @a.to_i(16) / 255.0
12
+ [ColorModes::Rgb.new(r, g, b, a), @format]
13
+ end
14
+
15
+ class << self
16
+ def from_hex3(format, r, g, b)
17
+ new(format || :hex3, r * 2, g * 2, b * 2)
18
+ end
19
+
20
+ def from_hex6(format, r, g, b)
21
+ new(format, r, g, b)
22
+ end
23
+
24
+ def from_hex8(format, r, g, b, a)
25
+ new(format || :hex8, r, g, b, a)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHsl < Base
4
+ def initialize(format, hsl)
5
+ @format = format || :hsl
6
+ @hsl = hsl
7
+ end
8
+
9
+ def generate
10
+ [Converters::RgbConverter.convert_hsl(@hsl), @format]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHslValues < Base
4
+ def initialize(format, h, s, l, a = 1)
5
+ s = to_percentage(s)
6
+ l = to_percentage(l)
7
+
8
+ @format = format
9
+ @hsl = ColorModes::Hsl.new(h, s, l, a)
10
+ end
11
+
12
+ def generate
13
+ FromHsl.new(@format, @hsl).generate
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHsv < Base
4
+ def initialize(format, hsv)
5
+ @format = format || :hsv
6
+ @hsv = hsv
7
+ end
8
+
9
+ def generate
10
+ [Converters::RgbConverter.convert_hsv(@hsv), @format]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromHsvValues < Base
4
+ def initialize(format, h, s, v, a = 1)
5
+ s = to_percentage(s)
6
+ v = to_percentage(v)
7
+
8
+ @format = format
9
+ @hsv = ColorModes::Hsv.new(h, s, v, a)
10
+ end
11
+
12
+ def generate
13
+ FromHsv.new(@format, @hsv).generate
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromRgb < Base
4
+ def initialize(format, rgb)
5
+ @format = format || :rgb
6
+ @rgb = rgb
7
+ end
8
+
9
+ def generate
10
+ FromRgbValues.new(@format, @rgb.r, @rgb.g, @rgb.b, @rgb.a).generate
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromRgbValues < Base
4
+ def initialize(format, r, g, b, a = 1)
5
+ @format = format
6
+ @r, @g, @b, @a = r, g, b, a
7
+ end
8
+
9
+ def generate
10
+ r, g, b = [@r, @g, @b].map { |n| bound01(n, 255) * 255 }
11
+ a = bound_alpha(@a)
12
+ [ColorModes::Rgb.new(r, g, b, a), @format]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,78 @@
1
+ module Chroma
2
+ module RgbGenerator
3
+ class FromString < Base
4
+ def self.matchers
5
+ @matchers ||= begin
6
+ # TinyColor.js matchers
7
+ css_int = '[-\\+]?\\d+%?'
8
+ css_num = '[-\\+]?\\d*\\.\\d+%?'
9
+ css_unit = "(?:#{css_num})|(?:#{css_int})"
10
+ permissive_prefix = '[\\s|\\(]+('
11
+ permissive_delim = ')[,|\\s]+('
12
+ permissive_suffix = ')\\s*\\)?'
13
+ permissive_match3 = "#{permissive_prefix}#{[css_unit] * 3 * permissive_delim}#{permissive_suffix}"
14
+ permissive_match4 = "#{permissive_prefix}#{[css_unit] * 4 * permissive_delim}#{permissive_suffix}"
15
+ hex_match = '[0-9a-fA-F]'
16
+
17
+ {
18
+ rgb: { regex: /rgb#{permissive_match3}/, class_name: :FromRgbValues },
19
+ rgba: { regex: /rgba#{permissive_match4}/, class_name: :FromRgbValues },
20
+ hsl: { regex: /hsl#{permissive_match3}/, class_name: :FromHslValues },
21
+ hsla: { regex: /hsla#{permissive_match4}/, class_name: :FromHslValues },
22
+ hsv: { regex: /hsv#{permissive_match3}/, class_name: :FromHsvValues },
23
+ hsva: { regex: /hsva#{permissive_match4}/, class_name: :FromHsvValues },
24
+ hex3: { regex: /^#?#{"(#{hex_match}{1})" * 3}$/, class_name: :FromHexStringValues, builder: :from_hex3 },
25
+ hex6: { regex: /^#?#{"(#{hex_match}{2})" * 3}$/, class_name: :FromHexStringValues, builder: :from_hex6 },
26
+ hex8: { regex: /^#?#{"(#{hex_match}{2})" * 4}$/, class_name: :FromHexStringValues, builder: :from_hex8 }
27
+ }.freeze
28
+ end
29
+ end
30
+
31
+ def initialize(input)
32
+ @input = normalize_input(input)
33
+ end
34
+
35
+ def generate
36
+ get_generator.generate
37
+ end
38
+
39
+ private
40
+
41
+ def get_generator
42
+ if color = Chroma.hex_from_name(@input)
43
+ format = :name
44
+ else
45
+ format = nil
46
+ color = @input
47
+ end
48
+
49
+ match = nil
50
+
51
+ _, hash = matchers.find do |_, h|
52
+ !(match = h[:regex].match(color)).nil?
53
+ end
54
+
55
+ raise 'Unrecognized color' if match.nil?
56
+
57
+ build_generator(match[1..-1], hash[:class_name], hash[:builder], format)
58
+ end
59
+
60
+ def build_generator(args, class_name, builder, format)
61
+ builder ||= :new
62
+ klass = RgbGenerator.const_get(class_name)
63
+ klass.__send__(builder, *([format] + args))
64
+ end
65
+
66
+ def normalize_input(input)
67
+ input.clone.tap do |str|
68
+ str.strip!
69
+ str.downcase!
70
+ end
71
+ end
72
+
73
+ def matchers
74
+ self.class.matchers
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ module Chroma
2
+ VERSION = '0.0.1.alpha.1'
3
+ end
@@ -0,0 +1,149 @@
1
+ aliceblue: 'f0f8ff'
2
+ antiquewhite: 'faebd7'
3
+ aqua: '0ff'
4
+ aquamarine: '7fffd4'
5
+ azure: 'f0ffff'
6
+ beige: 'f5f5dc'
7
+ bisque: 'ffe4c4'
8
+ black: '000'
9
+ blanchedalmond: 'ffebcd'
10
+ blue: '00f'
11
+ blueviolet: '8a2be2'
12
+ brown: 'a52a2a'
13
+ burlywood: 'deb887'
14
+ burntsienna: 'ea7e5d'
15
+ cadetblue: '5f9ea0'
16
+ chartreuse: '7fff00'
17
+ chocolate: 'd2691e'
18
+ coral: 'ff7f50'
19
+ cornflowerblue: '6495ed'
20
+ cornsilk: 'fff8dc'
21
+ crimson: 'dc143c'
22
+ cyan: '0ff'
23
+ darkblue: '00008b'
24
+ darkcyan: '008b8b'
25
+ darkgoldenrod: 'b8860b'
26
+ darkgray: 'a9a9a9'
27
+ darkgreen: '006400'
28
+ darkgrey: 'a9a9a9'
29
+ darkkhaki: 'bdb76b'
30
+ darkmagenta: '8b008b'
31
+ darkolivegreen: '556b2f'
32
+ darkorange: 'ff8c00'
33
+ darkorchid: '9932cc'
34
+ darkred: '8b0000'
35
+ darksalmon: 'e9967a'
36
+ darkseagreen: '8fbc8f'
37
+ darkslateblue: '483d8b'
38
+ darkslategray: '2f4f4f'
39
+ darkslategrey: '2f4f4f'
40
+ darkturquoise: '00ced1'
41
+ darkviolet: '9400d3'
42
+ deeppink: 'ff1493'
43
+ deepskyblue: '00bfff'
44
+ dimgray: '696969'
45
+ dimgrey: '696969'
46
+ dodgerblue: '1e90ff'
47
+ firebrick: 'b22222'
48
+ floralwhite: 'fffaf0'
49
+ forestgreen: '228b22'
50
+ fuchsia: 'f0f'
51
+ gainsboro: 'dcdcdc'
52
+ ghostwhite: 'f8f8ff'
53
+ gold: 'ffd700'
54
+ goldenrod: 'daa520'
55
+ gray: '808080'
56
+ green: '008000'
57
+ greenyellow: 'adff2f'
58
+ grey: '808080'
59
+ honeydew: 'f0fff0'
60
+ hotpink: 'ff69b4'
61
+ indianred: 'cd5c5c'
62
+ indigo: '4b0082'
63
+ ivory: 'fffff0'
64
+ khaki: 'f0e68c'
65
+ lavender: 'e6e6fa'
66
+ lavenderblush: 'fff0f5'
67
+ lawngreen: '7cfc00'
68
+ lemonchiffon: 'fffacd'
69
+ lightblue: 'add8e6'
70
+ lightcoral: 'f08080'
71
+ lightcyan: 'e0ffff'
72
+ lightgoldenrodyellow: 'fafad2'
73
+ lightgray: 'd3d3d3'
74
+ lightgreen: '90ee90'
75
+ lightgrey: 'd3d3d3'
76
+ lightpink: 'ffb6c1'
77
+ lightsalmon: 'ffa07a'
78
+ lightseagreen: '20b2aa'
79
+ lightskyblue: '87cefa'
80
+ lightslategray: '789'
81
+ lightslategrey: '789'
82
+ lightsteelblue: 'b0c4de'
83
+ lightyellow: 'ffffe0'
84
+ lime: '0f0'
85
+ limegreen: '32cd32'
86
+ linen: 'faf0e6'
87
+ magenta: 'f0f'
88
+ maroon: '800000'
89
+ mediumaquamarine: '66cdaa'
90
+ mediumblue: '0000cd'
91
+ mediumorchid: 'ba55d3'
92
+ mediumpurple: '9370db'
93
+ mediumseagreen: '3cb371'
94
+ mediumslateblue: '7b68ee'
95
+ mediumspringgreen: '00fa9a'
96
+ mediumturquoise: '48d1cc'
97
+ mediumvioletred: 'c71585'
98
+ midnightblue: '191970'
99
+ mintcream: 'f5fffa'
100
+ mistyrose: 'ffe4e1'
101
+ moccasin: 'ffe4b5'
102
+ navajowhite: 'ffdead'
103
+ navy: '000080'
104
+ oldlace: 'fdf5e6'
105
+ olive: '808000'
106
+ olivedrab: '6b8e23'
107
+ orange: 'ffa500'
108
+ orangered: 'ff4500'
109
+ orchid: 'da70d6'
110
+ palegoldenrod: 'eee8aa'
111
+ palegreen: '98fb98'
112
+ paleturquoise: 'afeeee'
113
+ palevioletred: 'db7093'
114
+ papayawhip: 'ffefd5'
115
+ peachpuff: 'ffdab9'
116
+ peru: 'cd853f'
117
+ pink: 'ffc0cb'
118
+ plum: 'dda0dd'
119
+ powderblue: 'b0e0e6'
120
+ purple: '800080'
121
+ rebeccapurple: '663399'
122
+ red: 'f00'
123
+ rosybrown: 'bc8f8f'
124
+ royalblue: '4169e1'
125
+ saddlebrown: '8b4513'
126
+ salmon: 'fa8072'
127
+ sandybrown: 'f4a460'
128
+ seagreen: '2e8b57'
129
+ seashell: 'fff5ee'
130
+ sienna: 'a0522d'
131
+ silver: 'c0c0c0'
132
+ skyblue: '87ceeb'
133
+ slateblue: '6a5acd'
134
+ slategray: '708090'
135
+ slategrey: '708090'
136
+ snow: 'fffafa'
137
+ springgreen: '00ff7f'
138
+ steelblue: '4682b4'
139
+ tan: 'd2b48c'
140
+ teal: '008080'
141
+ thistle: 'd8bfd8'
142
+ tomato: 'ff6347'
143
+ turquoise: '40e0d0'
144
+ violet: 'ee82ee'
145
+ wheat: 'f5deb3'
146
+ white: 'fff'
147
+ whitesmoke: 'f5f5f5'
148
+ yellow: 'ff0'
149
+ yellowgreen: '9acd32'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chroma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Fairbank
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Chroma is a color manipulation and palette generation gem.
42
+ email:
43
+ - elpapapollo@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - chroma.gemspec
54
+ - lib/chroma.rb
55
+ - lib/chroma/color.rb
56
+ - lib/chroma/color/attributes.rb
57
+ - lib/chroma/color/modifiers.rb
58
+ - lib/chroma/color/serializers.rb
59
+ - lib/chroma/color_modes.rb
60
+ - lib/chroma/converters/base.rb
61
+ - lib/chroma/converters/hsl_converter.rb
62
+ - lib/chroma/converters/hsv_converter.rb
63
+ - lib/chroma/converters/rgb_converter.rb
64
+ - lib/chroma/extensions/string.rb
65
+ - lib/chroma/harmonies.rb
66
+ - lib/chroma/helpers/bounders.rb
67
+ - lib/chroma/rgb_generator.rb
68
+ - lib/chroma/rgb_generator/base.rb
69
+ - lib/chroma/rgb_generator/from_hex_string_values.rb
70
+ - lib/chroma/rgb_generator/from_hsl.rb
71
+ - lib/chroma/rgb_generator/from_hsl_values.rb
72
+ - lib/chroma/rgb_generator/from_hsv.rb
73
+ - lib/chroma/rgb_generator/from_hsv_values.rb
74
+ - lib/chroma/rgb_generator/from_rgb.rb
75
+ - lib/chroma/rgb_generator/from_rgb_values.rb
76
+ - lib/chroma/rgb_generator/from_string.rb
77
+ - lib/chroma/version.rb
78
+ - lib/support/named_colors.yml
79
+ homepage: https://github.com/jfairbank/chroma
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.3.1
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.4.5
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Color manipulation and palette generation.
103
+ test_files: []