colorable 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/colorable/colorset.rb
CHANGED
@@ -5,56 +5,42 @@ module Colorable
|
|
5
5
|
include Enumerable
|
6
6
|
extend Forwardable
|
7
7
|
|
8
|
-
|
8
|
+
# Create a X11 colorset object.
|
9
|
+
#
|
10
|
+
# options::keys should be:
|
11
|
+
# +order+:: :NAME(default), :RGB, :HSB or :HEX can be specified.
|
12
|
+
# +dir+:: set :+(default) to increment order, :- to decrement order.
|
13
|
+
# +colorset+:: set original colorset other than X11 if any.
|
14
|
+
def initialize(opt={})
|
15
|
+
opt = { order: :name, dir: :+ }.merge(opt)
|
9
16
|
@pos = 0
|
10
|
-
@colorset =
|
11
|
-
colorset || COLORNAMES.map { |name, rgb| Colorable::Color.new(name) }
|
17
|
+
@colorset = opt[:colorset] ? opt[:colorset] : build_colorset(opt)
|
12
18
|
end
|
13
19
|
|
14
20
|
def_delegators :@colorset, :size, :first, :last, :to_a
|
15
21
|
|
16
|
-
# +Colorset[:order]+ create a ordered colorset by passing a order key.
|
17
|
-
def self.[](order, dir=:+, colorset=nil)
|
18
|
-
rgb = [:red, :green, :blue]
|
19
|
-
hsb = [:hue, :sat, :bright]
|
20
|
-
blk =
|
21
|
-
case order
|
22
|
-
when :red, :blue, :green
|
23
|
-
->color{ color.rgb.move_to_top rgb.index(order) }
|
24
|
-
when :hue, :sat, :bright
|
25
|
-
->color{ color.hsb.move_to_top hsb.index(order) }
|
26
|
-
else
|
27
|
-
->color{ color.send order }
|
28
|
-
end
|
29
|
-
|
30
|
-
case dir
|
31
|
-
when :+
|
32
|
-
new(colorset).sort_by(&blk)
|
33
|
-
when :-
|
34
|
-
new(colorset).sort_by(&blk).reverse
|
35
|
-
else
|
36
|
-
raise ArgumentError, "it must ':+' or ':-'"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
22
|
def each(&blk)
|
41
23
|
@colorset.each(&blk)
|
42
24
|
end
|
43
25
|
|
26
|
+
# Returns a top color object in colorset
|
44
27
|
def at(pos=0)
|
45
28
|
@colorset[(@pos+pos)%size]
|
46
29
|
end
|
47
30
|
|
31
|
+
# Returns a next color object in colorset
|
48
32
|
def next(n=1)
|
49
33
|
@pos = (@pos+n)%size
|
50
34
|
at
|
51
35
|
end
|
52
36
|
|
37
|
+
# Returns a previous color object in colorset
|
53
38
|
def prev(n=1)
|
54
39
|
@pos = (@pos-n)%size
|
55
40
|
at
|
56
41
|
end
|
57
42
|
|
43
|
+
# Rewind a cursor to the top
|
58
44
|
def rewind
|
59
45
|
@pos = 0
|
60
46
|
at
|
@@ -65,17 +51,60 @@ module Colorable
|
|
65
51
|
(@pos+idx)%size if idx
|
66
52
|
end
|
67
53
|
|
54
|
+
# Returns a sorted colorset defined by passed block
|
68
55
|
def sort_by(&blk)
|
69
|
-
self.class.new @colorset.sort_by(&blk)
|
56
|
+
self.class.new colorset: @colorset.sort_by(&blk)
|
70
57
|
end
|
71
58
|
|
59
|
+
# Returns a reversed colorset
|
72
60
|
def reverse
|
73
|
-
self.class.new @colorset.reverse
|
61
|
+
self.class.new colorset: @colorset.reverse
|
74
62
|
end
|
75
63
|
|
76
64
|
def to_s
|
77
|
-
"#<%s %d/%d pos='%s
|
65
|
+
"#<%s %d/%d pos='%s/%s/%s'>" % [:Colorset, @pos, size, at.name, at.rgb, at.hsb]
|
78
66
|
end
|
79
67
|
alias :inspect :to_s
|
68
|
+
|
69
|
+
private
|
70
|
+
def build_colorset(opt)
|
71
|
+
rgb_part = [:red, :green, :blue]
|
72
|
+
hsb_part = [:hue, :sat, :bright]
|
73
|
+
|
74
|
+
order = opt[:order].downcase.intern
|
75
|
+
|
76
|
+
mode =
|
77
|
+
case order
|
78
|
+
when :name then :NAME
|
79
|
+
when :rgb, *rgb_part then :RGB
|
80
|
+
when :hsb, :hsv, *hsb_part then :HSB
|
81
|
+
else
|
82
|
+
raise ArgumentError, "Invalid order option given"
|
83
|
+
end
|
84
|
+
|
85
|
+
colorset = COLORNAMES.map do |name, _|
|
86
|
+
Colorable::Color.new(name).tap {|c| c.mode = mode }
|
87
|
+
end
|
88
|
+
|
89
|
+
order_cond =
|
90
|
+
case order
|
91
|
+
when *rgb_part
|
92
|
+
->color{ color.rgb.move_to_top rgb_part.index(order) }
|
93
|
+
when *hsb_part
|
94
|
+
->color{ color.hsb.move_to_top hsb_part.index(order) }
|
95
|
+
when :name, :rgb, :hsb, :hsv
|
96
|
+
->color{ color.send order }
|
97
|
+
end
|
98
|
+
|
99
|
+
case opt[:dir].intern
|
100
|
+
when :+
|
101
|
+
colorset.sort_by(&order_cond)
|
102
|
+
when :-
|
103
|
+
colorset.sort_by(&order_cond).reverse
|
104
|
+
else
|
105
|
+
raise ArgumentError, "Invalid dir option given"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
80
109
|
end
|
81
110
|
end
|
data/lib/colorable/converter.rb
CHANGED
@@ -1,20 +1,15 @@
|
|
1
1
|
module Colorable
|
2
2
|
module Converter
|
3
|
-
class NoNameError < StandardError; end
|
4
|
-
|
5
3
|
def name2rgb(name)
|
6
|
-
COLORNAMES.assoc(name)
|
7
|
-
rescue
|
8
|
-
raise NoNameError, "'#{name}' not exist"
|
4
|
+
COLORNAMES.assoc(name).tap{|c, rgb| break rgb if c }
|
9
5
|
end
|
10
6
|
|
11
7
|
def rgb2name(rgb)
|
12
|
-
|
13
|
-
|
8
|
+
COLORNAMES.rassoc(rgb)
|
9
|
+
.tap { |c, _| break c if c }
|
14
10
|
end
|
15
11
|
|
16
12
|
def rgb2hsb(rgb)
|
17
|
-
validate_rgb(rgb)
|
18
13
|
r, g, b = rgb.map(&:to_f)
|
19
14
|
hue = Math.atan2(Math.sqrt(3)*(g-b), 2*r-g-b).to_degree
|
20
15
|
|
@@ -28,7 +23,6 @@ module Colorable
|
|
28
23
|
|
29
24
|
class NotImplemented < StandardError; end
|
30
25
|
def rgb2hsl(rgb)
|
31
|
-
validate_rgb(rgb)
|
32
26
|
raise NotImplemented, 'Not Implemented Yet'
|
33
27
|
r, g, b = rgb.map(&:to_f)
|
34
28
|
hue = Math.atan2(Math.sqrt(3)*(g-b), 2*r-g-b).to_degree
|
@@ -41,7 +35,6 @@ module Colorable
|
|
41
35
|
end
|
42
36
|
|
43
37
|
def hsb2rgb(hsb)
|
44
|
-
validate_hsb(hsb)
|
45
38
|
hue, sat, bright = hsb
|
46
39
|
norm = ->range{ hue.norm(range, 0..255) }
|
47
40
|
rgb_h =
|
@@ -51,7 +44,7 @@ module Colorable
|
|
51
44
|
when 120..180 then [0, 255, norm[120..180]]
|
52
45
|
when 180..240 then [0, 255-norm[180..240], 255]
|
53
46
|
when 240..300 then [norm[240..300], 0, 255]
|
54
|
-
when 300..360 then [255, 0, 255-norm[300
|
47
|
+
when 300..360 then [255, 0, 255-norm[300..360]]
|
55
48
|
end
|
56
49
|
rgb_s = rgb_h.map { |val| val + (255-val) * (1-sat/100.0) }
|
57
50
|
rgb_s.map { |val| (val * bright/100.0).round }
|
@@ -59,7 +52,6 @@ module Colorable
|
|
59
52
|
alias :hsv2rgb :hsb2rgb
|
60
53
|
|
61
54
|
def rgb2hex(rgb)
|
62
|
-
validate_rgb(rgb)
|
63
55
|
hex = rgb.map do |val|
|
64
56
|
val.to_s(16).tap { |h| break "0#{h}" if h.size==1 }
|
65
57
|
end
|
@@ -67,35 +59,8 @@ module Colorable
|
|
67
59
|
end
|
68
60
|
|
69
61
|
def hex2rgb(hex)
|
70
|
-
validate_hex(hex)
|
71
62
|
_, *hex = hex.unpack('A1A2A2A2')
|
72
63
|
hex.map { |val| val.to_i(16) }
|
73
64
|
end
|
74
|
-
|
75
|
-
private
|
76
|
-
def validate_rgb(rgb)
|
77
|
-
if rgb.all? { |val| val.between?(0, 255) }
|
78
|
-
rgb
|
79
|
-
else
|
80
|
-
raise ArgumentError, "'#{rgb}' is invalid for a RGB value"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def validate_hsb(hsb)
|
85
|
-
h, *sb = hsb
|
86
|
-
if h.between?(0, 360) && sb.all? { |val| val.between?(0, 100) }
|
87
|
-
hsb
|
88
|
-
else
|
89
|
-
raise ArgumentError, "'#{hsb}' is invalid for a HSB value"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def validate_hex(hex)
|
94
|
-
if hex.match(/^#[0-9A-F]{6}$/i)
|
95
|
-
hex.upcase
|
96
|
-
else
|
97
|
-
raise ArgumentError, "'#{hex}' is invalid for a HEX value"
|
98
|
-
end
|
99
|
-
end
|
100
65
|
end
|
101
66
|
end
|
@@ -16,9 +16,11 @@ class Array
|
|
16
16
|
def same?(&blk)
|
17
17
|
self.uniq(&blk).size==1
|
18
18
|
end
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
21
|
+
class Pattern < Array
|
22
|
+
def ===(other)
|
23
|
+
zip(other).all? { |a, b| a === b }
|
24
|
+
end
|
24
25
|
end
|
26
|
+
|
data/lib/colorable/version.rb
CHANGED
@@ -0,0 +1,356 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
include Colorable
|
4
|
+
describe RGB do
|
5
|
+
describe ".new" do
|
6
|
+
context "without arguments" do
|
7
|
+
subject { RGB.new }
|
8
|
+
its(:to_a) { should eql [0, 0, 0] }
|
9
|
+
its(:rgb) { should eql [0, 0, 0] }
|
10
|
+
its(:red) { should eql 0 }
|
11
|
+
its(:green) { should eql 0 }
|
12
|
+
its(:blue) { should eql 0 }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with arguments" do
|
16
|
+
subject { RGB.new 100, 255, 255 }
|
17
|
+
its(:to_a) { should eql [100, 255, 255] }
|
18
|
+
its(:rgb) { should eql [100, 255, 255] }
|
19
|
+
its(:red) { should eql 100 }
|
20
|
+
its(:green) { should eql 255 }
|
21
|
+
its(:blue) { should eql 255 }
|
22
|
+
end
|
23
|
+
|
24
|
+
context "pass out of RGB range" do
|
25
|
+
it "raise ArgumentError" do
|
26
|
+
expect { RGB.new(0, 0, 256) }.to raise_error ArgumentError
|
27
|
+
expect { RGB.new(-10, 0, 255) }.to raise_error ArgumentError
|
28
|
+
expect { RGB.new(256, 256, 256) }.to raise_error ArgumentError
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#+" do
|
34
|
+
context "pass an array of numbers" do
|
35
|
+
before(:all) { @rgb = RGB.new(100, 100, 100) }
|
36
|
+
subject { @rgb + [0, 50, 100] }
|
37
|
+
its(:rgb) { should eql [100, 150, 200] }
|
38
|
+
it "keep original same" do @rgb.rgb.should eql [100, 100, 100] end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when '+' makes out of RGB range or rack of numbers" do
|
42
|
+
it "raise ArgumentError" do
|
43
|
+
expect { RGB.new(100, 100, 100) + [0, 50, 200] }.to raise_error ArgumentError
|
44
|
+
expect { RGB.new(100, 100, 100) + [0, -150, 0] }.to raise_error ArgumentError
|
45
|
+
expect { RGB.new(100, 100, 100) + [0, 150] }.to raise_error ArgumentError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "pass a Fixnum" do
|
50
|
+
before(:all) { @rgb = RGB.new(100, 100, 100) }
|
51
|
+
it { (@rgb + 50).rgb.should eql [150, 150, 150] }
|
52
|
+
it "raise ArgumentError" do
|
53
|
+
expect { @rgb + 160 }.to raise_error ArgumentError
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "coerce make Fixnum#+ accept rgb object" do
|
58
|
+
it { (10 + RGB.new(100, 100, 100)).rgb.should eql [110, 110, 110] }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#-" do
|
63
|
+
context "pass an array of numbers" do
|
64
|
+
before(:all) { @rgb = RGB.new(100, 100, 100) }
|
65
|
+
subject { @rgb - [0, 50, 100] }
|
66
|
+
its(:rgb) { should eql [100, 50, 0] }
|
67
|
+
it "keep original same" do @rgb.rgb.should eql [100, 100, 100] end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when '-' makes out of RGB range" do
|
71
|
+
it "raise ArgumentError" do
|
72
|
+
expect { RGB.new(100, 100, 100) - [0, 50, 200] }.to raise_error ArgumentError
|
73
|
+
expect { RGB.new(100, 100, 100) - [0, -250, 0] }.to raise_error ArgumentError
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "pass a Fixnum" do
|
78
|
+
before(:all) { @rgb = RGB.new(100, 100, 100) }
|
79
|
+
it { (@rgb - 50).rgb.should eql [50, 50, 50] }
|
80
|
+
it "raise ArgumentError" do
|
81
|
+
expect { @rgb - 160 }.to raise_error ArgumentError
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#to_s" do
|
87
|
+
it { RGB.new(0, 50, 100).to_s.should eql "rgb(0,50,100)"}
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#to_name" do
|
91
|
+
it { RGB.new(240, 248, 255).to_name.should eql 'Alice Blue' }
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#to_hsb" do
|
95
|
+
it { RGB.new(240, 248, 255).to_hsb.should eql [208, 6, 100] }
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#to_hex" do
|
99
|
+
it { RGB.new(240, 248, 255).to_hex.should eql '#F0F8FF' }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe HSB do
|
104
|
+
describe ".new" do
|
105
|
+
context "without arguments" do
|
106
|
+
subject { HSB.new }
|
107
|
+
its(:to_a) { should eql [0, 0, 0] }
|
108
|
+
its(:hsb) { should eql [0, 0, 0] }
|
109
|
+
its(:hue) { should eql 0 }
|
110
|
+
its(:sat) { should eql 0 }
|
111
|
+
its(:bright) { should eql 0 }
|
112
|
+
end
|
113
|
+
|
114
|
+
context "with arguments" do
|
115
|
+
subject { HSB.new 300, 70, 90 }
|
116
|
+
its(:to_a) { should eql [300, 70, 90] }
|
117
|
+
its(:hsb) { should eql [300, 70, 90] }
|
118
|
+
its(:hue) { should eql 300 }
|
119
|
+
its(:sat) { should eql 70 }
|
120
|
+
its(:bright) { should eql 90 }
|
121
|
+
end
|
122
|
+
|
123
|
+
context "pass out of HSB range" do
|
124
|
+
it "raise ArgumentError" do
|
125
|
+
expect { HSB.new(0, 0, 120) }.to raise_error ArgumentError
|
126
|
+
expect { HSB.new(360, 0, 80) }.to raise_error ArgumentError
|
127
|
+
expect { HSB.new(0, -10, 0) }.to raise_error ArgumentError
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#+" do
|
133
|
+
context "pass an array of numbers" do
|
134
|
+
before(:all) { @hsb = HSB.new(300, 70, 90) }
|
135
|
+
subject { @hsb + [0, 5, 10] }
|
136
|
+
its(:hsb) { should eql [300, 75, 100] }
|
137
|
+
it "keep original same" do @hsb.hsb.should eql [300, 70, 90] end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when '+' makes out of HSB range or rack of numbers" do
|
141
|
+
it "raise ArgumentError" do
|
142
|
+
expect { HSB.new(300, 70, 90) + [0, 50, 0] }.to raise_error ArgumentError
|
143
|
+
expect { HSB.new(300, 70, 90) + [0, 0, -100] }.to raise_error ArgumentError
|
144
|
+
expect { HSB.new(300, 70, 90) + [0, 5] }.to raise_error ArgumentError
|
145
|
+
expect { HSB.new(300, 70, 90) + 5 }.to raise_error ArgumentError
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "#-" do
|
151
|
+
context "pass an array of numbers" do
|
152
|
+
before(:all) { @hsb = HSB.new(300, 70, 90) }
|
153
|
+
subject { @hsb - [0, 5, 10] }
|
154
|
+
its(:hsb) { should eql [300, 65, 80] }
|
155
|
+
it "keep original same" do @hsb.hsb.should eql [300, 70, 90] end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when '-' makes out of HSB range" do
|
159
|
+
it "raise ArgumentError" do
|
160
|
+
expect { HSB.new(300, 7, 90) - [305, 0, 10] }.to raise_error ArgumentError
|
161
|
+
expect { HSB.new(300, 70, 90) - [0, -35, 0] }.to raise_error ArgumentError
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "#to_s" do
|
167
|
+
it { HSB.new(0, 50, 100).to_s.should eql "hsb(0,50,100)"}
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "#to_name" do
|
171
|
+
it { HSB.new(208, 6, 100).to_name.should eql 'Alice Blue' }
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "#to_rgb" do
|
175
|
+
it { HSB.new(208, 6, 100).to_rgb.should eql [240, 248, 255] }
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "#to_hex" do
|
179
|
+
it { HSB.new(208, 6, 100).to_hex.should eql '#F0F8FF' }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe NAME do
|
184
|
+
describe ".new" do
|
185
|
+
context "with valid name" do
|
186
|
+
subject { NAME.new :alice_blue }
|
187
|
+
its(:to_s) { should eql 'Alice Blue' }
|
188
|
+
its(:name) { should eql 'Alice Blue' }
|
189
|
+
its(:sym) { should eql :alice_blue }
|
190
|
+
end
|
191
|
+
|
192
|
+
context "with invalid name" do
|
193
|
+
it "raise ArgumentError" do
|
194
|
+
expect { NAME.new :abc_color }.to raise_error ArgumentError
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "dark?" do
|
200
|
+
it { NAME.new(:navy).dark?.should be_true }
|
201
|
+
it { NAME.new(:alice_blue).dark?.should be_false }
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "#+" do
|
205
|
+
context "pass an irregal argument" do
|
206
|
+
it "raise ArgumentError" do
|
207
|
+
expect { NAME.new(:alice_blue) + [0, 150, 100] }.to raise_error ArgumentError
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context "pass a Fixnum" do
|
212
|
+
before(:all) { @name = NAME.new(:alice_blue) }
|
213
|
+
it { (@name + 1).name.should eql 'Antique White' }
|
214
|
+
it { (@name + 2).name.should eql 'Aqua' }
|
215
|
+
end
|
216
|
+
|
217
|
+
context "coerce make Fixnum#+ accept name object" do
|
218
|
+
it { (1 + NAME.new(:alice_blue)).to_s.should eql 'Antique White' }
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "#-" do
|
223
|
+
context "pass an irregal argument" do
|
224
|
+
it "raise ArgumentError" do
|
225
|
+
expect { NAME.new(:alice_blue) - [0, 150, 100] }.to raise_error ArgumentError
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "pass a Fixnum" do
|
230
|
+
before(:all) { @name = NAME.new(:alice_blue) }
|
231
|
+
it { (@name - 1).name.should eql 'Yellow Green' }
|
232
|
+
it { (@name - 2).name.should eql 'Yellow' }
|
233
|
+
end
|
234
|
+
|
235
|
+
context "coerce make Fixnum#+ accept name object" do
|
236
|
+
it { (1 - NAME.new(:alice_blue)).to_s.should eql 'Yellow Green' }
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "#to_rgb" do
|
241
|
+
it { NAME.new('Alice Blue').to_rgb.should eql [240, 248, 255] }
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "#to_hsb" do
|
245
|
+
it { NAME.new('Alice Blue').to_hsb.should eql [208, 6, 100] }
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "#to_hex" do
|
249
|
+
it { NAME.new('Alice Blue').to_hex.should eql '#F0F8FF' }
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe HEX do
|
254
|
+
describe ".new" do
|
255
|
+
context "without arguments" do
|
256
|
+
subject { HEX.new }
|
257
|
+
its(:to_s) { should eql '#FFFFFF' }
|
258
|
+
its(:hex) { should eql '#FFFFFF' }
|
259
|
+
its(:to_a) { should eql ['FF', 'FF', 'FF'] }
|
260
|
+
end
|
261
|
+
|
262
|
+
context "with arguments" do
|
263
|
+
it { HEX.new('#FFFF00').to_s.should eql '#FFFF00' }
|
264
|
+
it { HEX.new('#ffff00').to_s.should eql '#FFFF00' }
|
265
|
+
it { HEX.new('FFFF00').to_s.should eql '#FFFF00' }
|
266
|
+
it { HEX.new('#ff0').to_s.should eql '#FFFF00' }
|
267
|
+
it { HEX.new(['FF', 'FF', '00']).to_s.should eql '#FFFF00' }
|
268
|
+
end
|
269
|
+
|
270
|
+
context "pass out of HEX range" do
|
271
|
+
it "raise ArgumentError" do
|
272
|
+
expect { HEX.new('#FFGG00') }.to raise_error ArgumentError
|
273
|
+
expect { HEX.new('aaxxxx') }.to raise_error ArgumentError
|
274
|
+
expect { HEX.new(['FF', 'FF', 00]) }.to raise_error ArgumentError
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe "#+" do
|
280
|
+
context "pass a HEX string" do
|
281
|
+
before(:all) { @hex = HEX.new('#FF0000') }
|
282
|
+
it { (@hex + '#00FFCC').hex.should eql '#FFFFCC'}
|
283
|
+
it { (@hex + '#00ffcc').hex.should eql '#FFFFCC'}
|
284
|
+
it { (@hex + '00FFCC').hex.should eql '#FFFFCC'}
|
285
|
+
it { (@hex + '#0FC').hex.should eql '#FFFFCC'}
|
286
|
+
it "keep original" do @hex.hex.should eql '#FF0000' end
|
287
|
+
end
|
288
|
+
|
289
|
+
context "out of HEX range" do
|
290
|
+
it "raise ArgumentError" do
|
291
|
+
expect { HEX.new('#FF0000') + '#010000' }.to raise_error ArgumentError
|
292
|
+
expect { HEX.new('#FF0000') + '#00ffgg' }.to raise_error ArgumentError
|
293
|
+
expect { HEX.new('#000000') + [0, 50, 100] }.to raise_error ArgumentError
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "pass a Fixnum" do
|
298
|
+
before(:all) { @hex = HEX.new('#000000') }
|
299
|
+
it { (@hex + 255).hex.should eql '#FFFFFF' }
|
300
|
+
it "raise ArgumentError" do
|
301
|
+
expect { @hex + 260 }.to raise_error ArgumentError
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "coerce make Fixnum#+ accept hex object" do
|
306
|
+
it { (255 + HEX.new('#000000')).hex.should eql '#FFFFFF' }
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe "#-" do
|
311
|
+
context "pass a HEX string" do
|
312
|
+
before(:all) { @hex = HEX.new('#00FFFF') }
|
313
|
+
it { (@hex - '#00FFCC').hex.should eql '#000033'}
|
314
|
+
it { (@hex - '#00ffcc').hex.should eql '#000033'}
|
315
|
+
it { (@hex - '00FFCC').hex.should eql '#000033'}
|
316
|
+
it { (@hex - '#0FC').hex.should eql '#000033'}
|
317
|
+
it "keep original" do @hex.hex.should eql '#00FFFF' end
|
318
|
+
end
|
319
|
+
|
320
|
+
context "out of HEX range" do
|
321
|
+
it "raise ArgumentError" do
|
322
|
+
expect { HEX.new('#FF0000') - '#000100' }.to raise_error ArgumentError
|
323
|
+
expect { HEX.new('#FF0000') - '#0000cc' }.to raise_error ArgumentError
|
324
|
+
expect { HEX.new('#000000') - [0, 50, 100] }.to raise_error ArgumentError
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context "pass a Fixnum" do
|
329
|
+
before(:all) { @hex = HEX.new('#FFFFFF') }
|
330
|
+
it { (@hex - 255).hex.should eql '#000000' }
|
331
|
+
it "raise ArgumentError" do
|
332
|
+
expect { @hex + 260 }.to raise_error ArgumentError
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context "coerce make Fixnum#+ accept hex object" do
|
337
|
+
it { (255 - HEX.new('#FFFFFF')).hex.should eql '#000000' }
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "#to_s" do
|
342
|
+
it { HEX.new('#F0F8FF').to_s.should eql '#F0F8FF' }
|
343
|
+
end
|
344
|
+
|
345
|
+
describe "#to_rgb" do
|
346
|
+
it { HEX.new('#F0F8FF').to_rgb.should eql [240, 248, 255] }
|
347
|
+
end
|
348
|
+
|
349
|
+
describe "#to_hsb" do
|
350
|
+
it { HEX.new('#F0F8FF').to_hsb.should eql [208, 6, 100] }
|
351
|
+
end
|
352
|
+
|
353
|
+
describe "#to_name" do
|
354
|
+
it { HEX.new('#F0F8FF').to_name.should eql 'Alice Blue' }
|
355
|
+
end
|
356
|
+
end
|