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
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
|