colorable 0.0.8 → 0.1.0
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 +4 -4
- data/README.md +98 -27
- data/lib/colorable.rb +1 -1
- data/lib/colorable/color.rb +125 -35
- data/lib/colorable/color_space.rb +260 -0
- data/lib/colorable/colorset.rb +59 -30
- data/lib/colorable/converter.rb +4 -39
- data/lib/colorable/system_extension.rb +6 -4
- data/lib/colorable/version.rb +1 -1
- data/spec/color_space_spec.rb +356 -0
- data/spec/color_spec.rb +220 -47
- data/spec/colorset_spec.rb +49 -44
- data/spec/converter_spec.rb +25 -44
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b79f5456ff48188f4232decead4443e0c511ba3f
|
4
|
+
data.tar.gz: cf8e2236927be3b23baaec50d220d112190076b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7fc1f13cefb37d408c10491150020f788445693855b9a07d39c3653298d739f5f4b3f4de4f8d7e3fe5e2db58f0d3976d0982a167b330c54558c9abb768bc87d
|
7
|
+
data.tar.gz: 66a27bbed8977cd6b543b86eb947a7fa5b9ece0fa5a40d1d7e0e7d110ac26b2472f3b69348bb9a83e7b7c69651459512a91c856c7e7b84fc91dfdda5280f6368
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Colorable
|
2
2
|
|
3
|
-
|
3
|
+
Colorable is a color handler written in Ruby which include Color and Colorset classes.
|
4
|
+
A color object provide a conversion between X11 colorname, RGB, HSB and HEX or other manipulations. a colorset object represent X11 colorset which can be manipulated like enumerable object.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -21,33 +22,103 @@ Or install it yourself as:
|
|
21
22
|
Create a color object:
|
22
23
|
|
23
24
|
require "colorable"
|
25
|
+
include Colorable
|
24
26
|
|
25
|
-
#
|
26
|
-
c =
|
27
|
-
c.
|
28
|
-
c.
|
29
|
-
c.
|
30
|
-
c.to_s #=> "
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
27
|
+
# with a X11 colorname
|
28
|
+
c = Color.new :lime_green
|
29
|
+
c.to_s #=> "Lime Green"
|
30
|
+
c.rgb.to_a #=> [50, 205, 50]
|
31
|
+
c.hsb.to_a #=> [120, 76, 80]
|
32
|
+
c.hex.to_s #=> "#32CD32"
|
33
|
+
c.dark? #=> false
|
34
|
+
|
35
|
+
# with Array of RGB values
|
36
|
+
c = Color.new [50, 205, 50]
|
37
|
+
c.to_s #=> "rgb(50,205,50)"
|
38
|
+
c.name.to_s #=> "Lime Green"
|
39
|
+
c.hsb.to_a #=> [120, 76, 80]
|
40
|
+
c.hex.to_s #=> "#32CD32"
|
41
|
+
|
42
|
+
# with a HEX string
|
43
|
+
c = Color.new '#32CD32'
|
44
|
+
c.to_s #=> "#32CD32"
|
45
|
+
|
46
|
+
# with a RGB, HSB or HEX object
|
47
|
+
c = Color.new RGB.new(50, 205, 50)
|
48
|
+
c = Color.new HSB.new(120, 76, 80)
|
49
|
+
c = Color.new HEX.new('#32CD32')
|
50
|
+
|
51
|
+
Manipulate color object:
|
52
|
+
|
53
|
+
c = Color.new :lime_green
|
54
|
+
|
55
|
+
c.to_s #=> "Lime Green"
|
56
|
+
c.rgb.to_a #=> [50, 205, 50]
|
57
|
+
c.hsb.to_a #=> [120, 76, 80]
|
58
|
+
c.hex.to_s #=> "#32CD32"
|
59
|
+
c.dark? #=> false
|
60
|
+
|
61
|
+
# info returns information of the color
|
62
|
+
c.info #=> {:NAME=>"Lime Green", :RGB=>[50, 205, 50], :HSB=>[120, 76, 80], :HEX=>"#32CD32", :MODE=>:NAME, :DARK=>false}
|
63
|
+
|
64
|
+
# next, prev returns next, prev color object in X11 color sequence
|
65
|
+
c.next.to_s #=> "Linen"
|
66
|
+
c.next(2).to_s #=> "Magenta"
|
67
|
+
c.prev.to_s #=> "Lime"
|
68
|
+
c.prev(2).to_s #=> "Light Yellow"
|
69
|
+
|
70
|
+
# +, - returns incremented or decremented color object
|
71
|
+
(c + 1).to_s #=> "Linen"
|
72
|
+
(c + 2).to_s #=> "Magenta"
|
73
|
+
(c - 1).to_s #=> "Lime"
|
74
|
+
(c - 2).to_s #=> "Light Yellow"
|
75
|
+
|
76
|
+
Color object has a mode which represent output mode of the color. Behaviours of `#to_s`, `next`, `prev`, `+`, `-` will be changed based on the mode. You can change the mode with `#mode=` between :NAME, :RGB, :HSB, :HEX.
|
77
|
+
|
78
|
+
c = Color.new 'Lime Green'
|
79
|
+
c.mode = :NAME
|
80
|
+
c.to_s #=> "Lime Green"
|
81
|
+
c.next.to_s #=> "Linen"
|
82
|
+
|
83
|
+
c.mode = :RGB
|
84
|
+
c.to_s #=> "rgb(50,205,50)"
|
85
|
+
c.next.to_s #=> "rgb(60,179,113)"
|
86
|
+
c.next.name.to_s #=> "Medium Sea Green"
|
87
|
+
(c + 10).to_s #=> "rgb(60,215,60)"
|
88
|
+
(c + [0, 50, 100]).to_s #=> "rgb(50, 255, 150)"
|
89
|
+
|
90
|
+
|
91
|
+
Create a X11 colorset object:
|
92
|
+
|
93
|
+
include Colorable
|
94
|
+
|
95
|
+
cs = Colorset.new #=> #<Colorset 0/144 pos='Alice Blue/rgb(240,248,255)/hsb(208,6,100)'>
|
96
|
+
|
97
|
+
# with option
|
98
|
+
cs = Colorset.new(order: :RGB) #=> #<Colorset 0/144 pos='Black/rgb(0,0,0)/hsb(0,0,0)'>
|
99
|
+
cs = Colorset.new(order: :HSB, dir: :-) #=> #<Colorset 0/144 pos='Light Pink/rgb(255,182,193)/hsb(352,29,100)'>
|
100
|
+
|
101
|
+
Manupilate colorset:
|
102
|
+
|
103
|
+
cs = Colorset.new
|
104
|
+
cs.size #=> 144
|
105
|
+
cs.at.to_s #=> "Alice Blue"
|
106
|
+
cs.at(1).to_s #=> "Antique White"
|
107
|
+
cs.at(2).to_s #=> "Aqua"
|
108
|
+
|
109
|
+
# next(prev) methods moves cursor position
|
110
|
+
cs.next.to_s #=> "Antique White"
|
111
|
+
cs.at.to_s #=> "Antique White"
|
112
|
+
cs.next.to_s #=> "Aqua"
|
113
|
+
cs.at.to_s #=> "Aqua"
|
114
|
+
cs.rewind
|
115
|
+
cs.at.to_s #=> "Alice Blue"
|
116
|
+
|
117
|
+
cs.map(&:to_s).take(10) #=> ["Alice Blue", "Antique White", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "Blanched Almond", "Blue"]
|
118
|
+
|
119
|
+
cs.sort_by(&:rgb).map(&:to_s).take(10) #=> ["Black", "Navy", "Dark Blue", "Medium Blue", "Blue", "Dark Green", "Green2", "Teal", "Dark Cyan", "Deep Sky Blue"]
|
120
|
+
|
121
|
+
cs.sort_by(&:hsb).map(&:to_s).take(10) #=> ["Black", "Dim Gray", "Gray2", "Dark Gray", "Gray", "Silver", "Light Gray", "Gainsboro", "White Smoke", "White"]
|
51
122
|
|
52
123
|
|
53
124
|
## Contributing
|
data/lib/colorable.rb
CHANGED
data/lib/colorable/color.rb
CHANGED
@@ -1,71 +1,161 @@
|
|
1
1
|
module Colorable
|
2
2
|
class Color
|
3
|
-
class
|
4
|
-
include Colorable::Converter
|
3
|
+
class NameError < StandardError; end
|
5
4
|
include Comparable
|
6
5
|
attr_reader :name, :rgb
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
# Create a Color object which has several representations of a color.
|
8
|
+
#
|
9
|
+
# +arg+ can be:
|
10
|
+
# String or Symbol of color name
|
11
|
+
# String of HEX color
|
12
|
+
# Array of RGB values
|
13
|
+
# NAME, RGB, HSB, HEX objects
|
14
|
+
#
|
15
|
+
# Color object has output mode, which is determined by +arg+ type.
|
16
|
+
def initialize(arg)
|
17
|
+
@name, @rgb, @hsb, @hex, @mode = set_variables(arg)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a current output mode
|
21
|
+
def mode
|
22
|
+
"#{@mode.class}"[/\w+$/].intern
|
23
|
+
end
|
24
|
+
|
25
|
+
# Set output mode.
|
26
|
+
def mode=(mode)
|
27
|
+
modes = [rgb, hsb, name, hex]
|
28
|
+
@mode = modes.detect { |m| m.class.to_s.match /#{mode}/i } || begin
|
29
|
+
raise ArgumentError, "Invalid mode given"
|
30
|
+
end
|
20
31
|
end
|
21
32
|
|
22
33
|
def to_s
|
23
|
-
|
34
|
+
@mode.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns information of the color object
|
38
|
+
def info
|
39
|
+
{
|
40
|
+
NAME: name.to_s,
|
41
|
+
RGB: rgb.to_a,
|
42
|
+
HSB: hsb.to_a,
|
43
|
+
HEX: hex.to_s,
|
44
|
+
MODE: mode,
|
45
|
+
DARK: dark?
|
46
|
+
}
|
24
47
|
end
|
25
48
|
|
26
49
|
def hex
|
27
|
-
@hex ||=
|
50
|
+
@hex ||= HEX.new rgb.to_hex
|
28
51
|
end
|
29
52
|
|
30
53
|
def hsb
|
31
|
-
@hsb ||=
|
54
|
+
@hsb ||= HSB.new *rgb.to_hsb
|
32
55
|
end
|
33
56
|
alias :hsv :hsb
|
34
57
|
|
35
|
-
%w(red green blue).
|
36
|
-
define_method(c) { rgb
|
58
|
+
%w(red green blue).each do |c|
|
59
|
+
define_method(c) { rgb.send c }
|
37
60
|
end
|
38
61
|
|
39
|
-
%w(hue sat bright).
|
40
|
-
define_method(
|
62
|
+
%w(hue sat bright).each do |c|
|
63
|
+
define_method(c) { hsb.send c }
|
41
64
|
end
|
42
65
|
|
43
66
|
def <=>(other)
|
44
|
-
self.
|
67
|
+
self.rgb <=> other.rgb
|
45
68
|
end
|
46
69
|
|
47
70
|
@@colorset = {}
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@@colorset[
|
71
|
+
# Returns a next color object in X11 colors.
|
72
|
+
# The color sequence is determined by its color mode.
|
73
|
+
def next(n=1)
|
74
|
+
@@colorset[mode] ||= Colorable::Colorset.new(order: mode)
|
75
|
+
idx = @@colorset[mode].find_index(self)
|
76
|
+
@@colorset[mode].at(idx+n).tap{|c| c.mode = mode } if idx
|
52
77
|
end
|
53
78
|
|
54
|
-
|
55
|
-
|
79
|
+
# Returns a previous color object in X11 colors.
|
80
|
+
# The color sequence is determined by its color mode.
|
81
|
+
def prev(n=1)
|
82
|
+
self.next(-n)
|
56
83
|
end
|
57
84
|
|
58
85
|
def dark?
|
59
|
-
DARK_COLORS.detect { |d| d ==
|
86
|
+
!!DARK_COLORS.detect { |d| d == name.to_s }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns a color object which has incremented color values.
|
90
|
+
# Array of values or a Fixnum is acceptable as an argument.
|
91
|
+
# Which values are affected is determined by its color mode.
|
92
|
+
def +(arg)
|
93
|
+
self.class.new @mode + arg
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns a color object which has decremented color values.
|
97
|
+
# Array of values or a Fixnum is acceptable as an argument.
|
98
|
+
# Which values are affected is determined by its color mode.
|
99
|
+
def -(arg)
|
100
|
+
self.class.new @mode - arg
|
60
101
|
end
|
61
102
|
|
62
103
|
private
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
104
|
+
def set_variables(arg)
|
105
|
+
case arg
|
106
|
+
when String, Symbol
|
107
|
+
begin
|
108
|
+
hex = HEX.new(arg)
|
109
|
+
name = NAME.new(hex.to_name) rescue nil
|
110
|
+
rgb = RGB.new *hex.to_rgb
|
111
|
+
hsb = nil
|
112
|
+
mode = hex
|
113
|
+
rescue ArgumentError
|
114
|
+
name = validate_name(arg)
|
115
|
+
rgb = RGB.new *name.to_rgb
|
116
|
+
hsb = nil
|
117
|
+
hex = nil
|
118
|
+
mode = name
|
119
|
+
end
|
120
|
+
when Array
|
121
|
+
rgb = RGB.new *arg
|
122
|
+
name = NAME.new(rgb.to_name) rescue nil
|
123
|
+
hsb = nil
|
124
|
+
hex = nil
|
125
|
+
mode = rgb
|
126
|
+
when RGB
|
127
|
+
rgb = arg
|
128
|
+
name = NAME.new(rgb.to_name) rescue nil
|
129
|
+
hsb = nil
|
130
|
+
hex = nil
|
131
|
+
mode = rgb
|
132
|
+
when HSB
|
133
|
+
hsb = arg
|
134
|
+
rgb = RGB.new *hsb.to_rgb
|
135
|
+
name = NAME.new(rgb.to_name) rescue nil
|
136
|
+
hex = nil
|
137
|
+
mode = hsb
|
138
|
+
when NAME
|
139
|
+
name = arg
|
140
|
+
rgb = RGB.new *name.to_rgb
|
141
|
+
hsb = nil
|
142
|
+
hex = nil
|
143
|
+
mode = name
|
144
|
+
when HEX
|
145
|
+
hex = arg
|
146
|
+
name = NAME.new(hex.to_name) rescue nil
|
147
|
+
rgb = RGB.new *hex.to_rgb
|
148
|
+
hsb = nil
|
149
|
+
mode = hex
|
150
|
+
else
|
151
|
+
raise ArgumentError
|
152
|
+
end
|
153
|
+
return name, rgb, hsb, hex, mode
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_name(name)
|
157
|
+
NAME.new(name).tap do |res|
|
158
|
+
raise NameError, "Invalid color name given" unless res.name
|
69
159
|
end
|
70
160
|
end
|
71
161
|
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
module Colorable
|
2
|
+
class ColorSpace
|
3
|
+
include Colorable::Converter
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
def <=>(other)
|
7
|
+
self.to_a <=> other.to_a
|
8
|
+
end
|
9
|
+
|
10
|
+
def move_to_top(idx)
|
11
|
+
arr = self.to_a
|
12
|
+
arr.insert 0, arr.delete_at(idx)
|
13
|
+
end
|
14
|
+
|
15
|
+
def +(arg)
|
16
|
+
raise "Subclass must implement it"
|
17
|
+
end
|
18
|
+
|
19
|
+
def -(arg)
|
20
|
+
arg = arg.is_a?(Fixnum) ? -arg : arg.map(&:-@)
|
21
|
+
self + arg
|
22
|
+
end
|
23
|
+
|
24
|
+
def coerce(arg)
|
25
|
+
[self, arg]
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
name = "#{self.class}"[/\w+$/].downcase
|
30
|
+
"#{name}(%i,%i,%i)" % to_a
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def validate(pattern, data)
|
35
|
+
case Array(data)
|
36
|
+
when Pattern[*Array(pattern)] then data
|
37
|
+
else
|
38
|
+
raise ArgumentError, "'#{data}' is invalid for a #{self.class} value"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class RGB < ColorSpace
|
44
|
+
attr_accessor :rgb, :r, :g, :b
|
45
|
+
def initialize(r=0,g=0,b=0)
|
46
|
+
@r, @g, @b = @rgb = validate_rgb([r, g, b])
|
47
|
+
end
|
48
|
+
alias :red :r
|
49
|
+
alias :green :g
|
50
|
+
alias :blue :b
|
51
|
+
alias :to_a :rgb
|
52
|
+
|
53
|
+
# Pass Array of [r, g, b] or a Fixnum.
|
54
|
+
# Returns new RGB object with added RGB.
|
55
|
+
def +(arg)
|
56
|
+
arg =
|
57
|
+
case arg
|
58
|
+
when Fixnum
|
59
|
+
[arg] * 3
|
60
|
+
when Array
|
61
|
+
raise ArgumentError, "Must be three numbers contained" unless arg.size==3
|
62
|
+
arg
|
63
|
+
else
|
64
|
+
raise ArgumentError, "Accept only Array of three numbers or a Fixnum"
|
65
|
+
end
|
66
|
+
new_rgb = self.rgb.zip(arg).map { |x, y| x + y }
|
67
|
+
self.class.new *new_rgb
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_name
|
71
|
+
rgb2name(self.to_a)
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_hsb
|
75
|
+
rgb2hsb(self.to_a)
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_hex
|
79
|
+
rgb2hex(self.to_a)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def validate_rgb(rgb)
|
84
|
+
validate([0..255, 0..255, 0..255], rgb)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class HSB < ColorSpace
|
89
|
+
attr_accessor :hsb, :h, :s, :b
|
90
|
+
def initialize(h=0,s=0,b=0)
|
91
|
+
@h, @s, @b = @hsb = validate_hsb([h, s, b])
|
92
|
+
end
|
93
|
+
alias :hue :h
|
94
|
+
alias :sat :s
|
95
|
+
alias :bright :b
|
96
|
+
alias :to_a :hsb
|
97
|
+
undef :coerce
|
98
|
+
|
99
|
+
# Pass Array of [h, s, b] or a Fixnum.
|
100
|
+
# Returns new HSB object with added HSB.
|
101
|
+
def +(arg)
|
102
|
+
arg =
|
103
|
+
case arg
|
104
|
+
when Array
|
105
|
+
raise ArgumentError, "Must be three numbers contained" unless arg.size==3
|
106
|
+
arg
|
107
|
+
else
|
108
|
+
raise ArgumentError, "Accept only Array of three numbers"
|
109
|
+
end
|
110
|
+
new_hsb = self.hsb.zip(arg).map { |x, y| x + y }
|
111
|
+
self.class.new *new_hsb
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_name
|
115
|
+
rgb2name(self.to_rgb)
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_rgb
|
119
|
+
hsb2rgb(self.to_a)
|
120
|
+
end
|
121
|
+
|
122
|
+
def to_hex
|
123
|
+
rgb2hex(self.to_rgb)
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
def validate_hsb(hsb)
|
128
|
+
validate([0..359, 0..100, 0..100], hsb)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class HEX < ColorSpace
|
133
|
+
attr_reader :hex
|
134
|
+
def initialize(hex='#FFFFFF')
|
135
|
+
@hex = validate_hex(hex)
|
136
|
+
end
|
137
|
+
alias :to_s :hex
|
138
|
+
|
139
|
+
def to_a
|
140
|
+
@hex.unpack('A1A2A2A2').drop(1)
|
141
|
+
end
|
142
|
+
|
143
|
+
def +(arg)
|
144
|
+
build_hex_with(:+, arg)
|
145
|
+
end
|
146
|
+
|
147
|
+
def -(arg)
|
148
|
+
build_hex_with(:-, arg)
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_rgb
|
152
|
+
hex2rgb(self.to_s)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_hsb
|
156
|
+
rgb2hsb(self.to_rgb)
|
157
|
+
end
|
158
|
+
|
159
|
+
def to_name
|
160
|
+
rgb2name(self.to_rgb)
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
def validate_hex(hex)
|
165
|
+
hex = hex.join if hex.is_a?(Array)
|
166
|
+
validate(/^#[0-9A-F]{6}$/i, hex_norm(hex))
|
167
|
+
end
|
168
|
+
|
169
|
+
def hex_norm(hex)
|
170
|
+
hex = hex.to_s.sub(/^#/, '').upcase
|
171
|
+
.sub(/^([0-9A-F])([0-9A-F])([0-9A-F])$/, '\1\1\2\2\3\3')
|
172
|
+
"##{hex}"
|
173
|
+
end
|
174
|
+
|
175
|
+
def rgb2hex(rgb)
|
176
|
+
hex = rgb.map do |val|
|
177
|
+
val.to_s(16).tap { |h| break "0#{h}" if h.size==1 }
|
178
|
+
end
|
179
|
+
'#' + hex.join.upcase
|
180
|
+
end
|
181
|
+
|
182
|
+
def hex2rgb(hex)
|
183
|
+
_, *hex = hex.unpack('A1A2A2A2')
|
184
|
+
hex.map { |val| val.to_i(16) }
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_hex_with(op, arg)
|
188
|
+
_rgb =
|
189
|
+
case arg
|
190
|
+
when Fixnum
|
191
|
+
[arg] * 3
|
192
|
+
when String
|
193
|
+
hex2rgb(validate_hex arg)
|
194
|
+
else
|
195
|
+
raise ArgumentError, "Accept only a Hex string or a Fixnum"
|
196
|
+
end
|
197
|
+
rgb = hex2rgb(self.hex).zip(_rgb).map { |x, y| x.send(op, y) }
|
198
|
+
self.class.new rgb2hex(rgb)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class NAME < ColorSpace
|
203
|
+
attr_accessor :name
|
204
|
+
attr_reader :sym
|
205
|
+
def initialize(name)
|
206
|
+
@name = find_name(name)
|
207
|
+
@sym = nil
|
208
|
+
end
|
209
|
+
|
210
|
+
alias :to_s :name
|
211
|
+
|
212
|
+
def sym
|
213
|
+
@name.gsub(/\s/, '_').downcase.intern if @name
|
214
|
+
end
|
215
|
+
|
216
|
+
def dark?
|
217
|
+
DARK_COLORS.detect { |d| d == self.name }
|
218
|
+
end
|
219
|
+
|
220
|
+
def <=>(other)
|
221
|
+
self.name <=> other.name
|
222
|
+
end
|
223
|
+
|
224
|
+
def +(n)
|
225
|
+
raise ArgumentError, 'Only accept a Fixnum' unless n.is_a?(Fixnum)
|
226
|
+
pos = COLORNAMES.find_index{|n,_| n==self.name} + n
|
227
|
+
self.class.new COLORNAMES.at(pos % COLORNAMES.size)[0]
|
228
|
+
end
|
229
|
+
|
230
|
+
def -(n)
|
231
|
+
raise ArgumentError, 'Only accept a Fixnum' unless n.is_a?(Fixnum)
|
232
|
+
self + -n
|
233
|
+
end
|
234
|
+
|
235
|
+
def coerce(arg)
|
236
|
+
[self, arg]
|
237
|
+
end
|
238
|
+
|
239
|
+
def to_rgb
|
240
|
+
name2rgb(self.to_s)
|
241
|
+
end
|
242
|
+
|
243
|
+
def to_hsb
|
244
|
+
rgb2hsb(self.to_rgb)
|
245
|
+
end
|
246
|
+
|
247
|
+
def to_hex
|
248
|
+
rgb2hex(self.to_rgb)
|
249
|
+
end
|
250
|
+
|
251
|
+
private
|
252
|
+
def find_name(name)
|
253
|
+
COLORNAMES.map(&:first).detect { |c|
|
254
|
+
[c, name].same? { |str| "#{str}".gsub(/[_\s]/,'').downcase }
|
255
|
+
} || begin
|
256
|
+
raise ArgumentError, "'#{name}' is not in X11 colorset."
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|