iq-color 0.9.2

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.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ /doc
3
+ /cov
4
+ /pkg
5
+ /.document
6
+ /.yardoc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in iq-color.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2011 Jamie Hill, SonicIQ Ltd. http://soniciq.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,66 @@
1
+ = IQ::Color
2
+
3
+ The IQ::Color gem provides simple classes for representing color values and handles the conversion to and from CSS3 color strings. For more information see: IQ::Color
4
+
5
+ == Install
6
+ gem install iq-color
7
+
8
+ == Usage
9
+
10
+ From 3 digit hex strings:
11
+ color = IQ::Color.from_css('#f80')
12
+ color.red #=> 255
13
+ color.green #=> 136
14
+ color.blue #=> 0
15
+ color.to_css #=> "#ff8800"
16
+
17
+ From 6 digit hex strings:
18
+ color = IQ::Color.from_css('#f5337b')
19
+ color.red #=> 245
20
+ color.green #=> 51
21
+ color.blue #=> 123
22
+ color.to_css #=> "#f5337b"
23
+
24
+ From rgb notation:
25
+ color = IQ::Color.from_css('rgb(127,127,255)')
26
+ color.red #=> 127
27
+ color.green #=> 127
28
+ color.blue #=> 255
29
+ color.to_css #=> "#7f7fff"
30
+
31
+ From rgba notation:
32
+ color = IQ::Color.from_css('rgba(127,127,255,0.4)')
33
+ color.red #=> 127
34
+ color.green #=> 127
35
+ color.blue #=> 255
36
+ color.alpha #=> 0.4
37
+ color.to_css #=> "rgba(127,127,255,0.4)"
38
+
39
+ Manually instantiate an RGB value:
40
+ color = IQ::Color.RGB.new(127, 127, 255)
41
+ color.to_css #=> "#7f7fff"
42
+
43
+ Manually instantiate an RGBA value:
44
+ color = IQ::Color.RGBA.new(127, 127, 255, 0.4)
45
+ color.to_css #=> "rgba(127,127,255,0.4)"
46
+
47
+ == Documentation
48
+
49
+ Documentation is handled with YARD[http://github.com/lsegal/yard]. You can
50
+ generate the documentation by running:
51
+
52
+ rake yard
53
+
54
+ == Note on Patches/Pull Requests
55
+
56
+ * Fork the project.
57
+ * Make your feature addition or bug fix.
58
+ * Add tests for it. This is important so I don't break it in a
59
+ future version unintentionally.
60
+ * Commit, do not mess with rakefile, version, or history.
61
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
62
+ * Send me a pull request. Bonus points for topic branches.
63
+
64
+ == Copyright
65
+
66
+ Copyright (c) 2011 Jamie Hill, SonicIQ Ltd. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => 'test'
5
+
6
+ require 'rake/testtask'
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << 'lib' << 'test'
9
+ test.pattern = 'test/**/*_test.rb'
10
+ test.verbose = true
11
+ end
12
+
13
+ begin
14
+ require 'yard'
15
+ YARD::Rake::YardocTask.new
16
+ rescue LoadError
17
+ task :yardoc do
18
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
19
+ end
20
+ end
data/iq-color.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "iq/color/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "iq-color"
7
+ s.version = IQ::Color::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jamie Hill"]
10
+ s.email = ["jamie@soniciq.com"]
11
+ s.homepage = "http://github.com/soniciq/iq-color"
12
+ s.summary = %q{A series of classes for handling color conversion.}
13
+ s.description = %q{IQ::Color provides simple classes for representing colour values and the conversion to and from CSS3 strings.}
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+ end
@@ -0,0 +1,5 @@
1
+ # The base class that color model classes should inherit.
2
+ class IQ::Color::Base # :nodoc:
3
+ COLOR_MATCH = /\s*(\d*\.?\d+\%?)\s*/
4
+ FLOAT_MATCH = /\s*(\d*\.?\d+)\s*/
5
+ end
@@ -0,0 +1,53 @@
1
+ # A class for representing RGB values.
2
+
3
+ class IQ::Color::RGB < IQ::Color::Base
4
+ attr_reader :red, :green, :blue
5
+
6
+ # Returns a new IQ::Color::RGB instance with the supplied rgb values.
7
+ def initialize(red, green, blue)
8
+ [red, green, blue].each do |color|
9
+ raise ArgumentError, 'Color values must be supplied as integers' unless color.is_a?(Integer)
10
+ raise ArgumentError, 'Color values must be in the range of 0-255' if color < 0 || color > 255
11
+ end
12
+ @red, @green, @blue = red, green, blue
13
+ end
14
+
15
+ # Returns the color as a css hex string e.g. <tt>'#ffeedd'</tt>.
16
+ def to_css
17
+ '#%02x%02x%02x' % [red, green, blue]
18
+ end
19
+
20
+ # Returns a new instance based on the css string supplied. Accepts both hex
21
+ # and 'rgb' notation e.g. <tt>'#fed'</tt>, <tt>'#ffeedd'</tt> or
22
+ # <tt>'rgb(255,238,221)'</tt> (note that white space is allowed either side
23
+ # of the commas). More on CSS3 colour strings can be found at:
24
+ # http://www.w3.org/TR/css3-color
25
+ #
26
+ def self.from_css(css_string)
27
+ raise ArgumentError, 'CSS color must be in the form of a string' unless css_string.is_a?(String)
28
+
29
+ if css_string[0, 1] == '#'
30
+ # hex notation e.g. '#fed' or '#ffeedd'
31
+ hex = css_string[1..-1]
32
+ colors = case hex.size
33
+ when 3 : hex.scan(/[0-9A-Fa-f]/).map { |channel| (channel * 2).to_i(16) }
34
+ when 6 : hex.scan(/[0-9A-Fa-f]{2}/).map { |channel| channel.to_i(16) }
35
+ else raise(ArgumentError, 'Hex colour must be in the format of "#fed" or "#ffeedd"')
36
+ end
37
+ new *colors
38
+ elsif match = css_string.match(/^rgb\(#{COLOR_MATCH},#{COLOR_MATCH},#{COLOR_MATCH}\)$/)
39
+ # 'rgb(n,n,n)' notation
40
+ new _flatten_percentage(match[1]), _flatten_percentage(match[2]), _flatten_percentage(match[3])
41
+ else
42
+ raise ArgumentError, 'Unrecognised colour format'
43
+ end
44
+ end
45
+
46
+ class << self
47
+ private
48
+
49
+ def _flatten_percentage(percentage_string)
50
+ percentage_string[-1, 1] == '%' ? ((percentage_string.chomp('%').to_f * 256) / 100).round : percentage_string.to_i
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ # A class for representing RGB values with an alpha channel.
2
+
3
+ class IQ::Color::RGBA < IQ::Color::RGB
4
+ attr_reader :alpha
5
+
6
+ # Returns a new IQ::Color::RGBA instance with the supplied rgb and alpha values.
7
+ def initialize(red, green, blue, alpha = 1.0)
8
+ raise ArgumentError, 'Alpha value must be an integer of float' unless alpha.is_a?(Integer) || alpha.is_a?(Float)
9
+ raise ArgumentError, 'Alpha value must be between 0.0 and 1.0' if alpha < 0 || alpha > 1
10
+ super red, green, blue
11
+ @alpha = alpha.to_f
12
+ end
13
+
14
+ # Returns the color as a css rgba string e.g. <tt>'rgba(14,20,40,0.4)'</tt>.
15
+ def to_css
16
+ 'rgba(%d,%d,%d,%s)' % [red, green, blue, alpha]
17
+ end
18
+
19
+ # Returns a new instance based on the css string supplied. Accepts hex, 'rgb'
20
+ # and 'rgba' notation e.g. <tt>'#fed'</tt>, <tt>'#ffeedd'</tt>,
21
+ # <tt>'rgb(255,238,221)'</tt> and <tt>'rgb(255,238,221,1.0)'</tt>
22
+ # (note that white space is allowed either side of the commas).
23
+ #
24
+ # If an <tt>'rgba'</tt> string is supplied then the 'a' segment is the alpha
25
+ # value between 0 and 1 (0 is fully transparent and 1 is fully opaque).
26
+ #
27
+ # A value of <tt>'transparent'</tt> may be supplied as a shortcut for
28
+ # <tt>rgba(0,0,0,0)</tt>.
29
+ #
30
+ # More on CSS3 colour strings can be found at:
31
+ # http://www.w3.org/TR/css3-color
32
+ #
33
+ def self.from_css(css_string)
34
+ if css_string == 'transparent'
35
+ new 0, 0, 0, 0
36
+ elsif match = css_string.match(/^rgba\(#{COLOR_MATCH},#{COLOR_MATCH},#{COLOR_MATCH},#{FLOAT_MATCH}\)$/)
37
+ # 'rgba(n,n,n,n)' notation
38
+ new _flatten_percentage(match[1]), _flatten_percentage(match[2]), _flatten_percentage(match[3]), match[4].to_f
39
+ else
40
+ super css_string
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ module IQ
2
+ module Color
3
+ VERSION = "0.9.2"
4
+ end
5
+ end
data/lib/iq/color.rb ADDED
@@ -0,0 +1,38 @@
1
+ module IQ # :nodoc:
2
+ module Color
3
+ # Returns a new instance based on the CSS3 color string supplied. Accepts
4
+ # both hex and 'rgb' notation e.g. <tt>'#fed'</tt>, <tt>'#ffeedd'</tt> and
5
+ # <tt>'rgb(255,238,221)'</tt> (note that white space is allowed either side
6
+ # of the commas). For both color notation formats, an IQ::Color:RGB
7
+ # instance is returned.
8
+ #
9
+ # In addition to the standard rgb notations above, the <tt>'rgba'</tt>
10
+ # notation can be supplied where 'a' is the alpha channel value between 0
11
+ # and 1 (0 is fully transparent and 1 is fully opaque). In this case a new
12
+ # IQ::Color::RGBA instance is returned.
13
+ #
14
+ # A value of <tt>'transparent'</tt> may be supplied as a shortcut for
15
+ # <tt>rgba(0,0,0,0)</tt> which will return a new IQ::Color::RGBA instance.
16
+ #
17
+ # More on CSS3 colour strings can be found at:
18
+ # http://www.w3.org/TR/css3-color
19
+ #
20
+ def self.from_css(css_string)
21
+ raise ArgumentError, 'Must supply a string' unless css_string.is_a?(String)
22
+
23
+ if css_string[0, 1] == '#' || css_string.match(/^rgb\(.*\)$/)
24
+ # RGB notations e.g. '#f00', '#ff0000' or 'rgb(n,n,n)'.
25
+ IQ::Color::RGB.from_css css_string
26
+ elsif css_string.match(/^rgba\(.*\)$/) || css_string == 'transparent'
27
+ # RGBA notation e.g. 'rgba(n,n,n,n)' or 'transparent' string.
28
+ IQ::Color::RGBA.from_css css_string
29
+ else
30
+ raise ArgumentError, 'Unrecognised CSS colour format'
31
+ end
32
+ end
33
+
34
+ autoload :Base, File.join(File.dirname(__FILE__), 'color', 'base')
35
+ autoload :RGB, File.join(File.dirname(__FILE__), 'color', 'rgb')
36
+ autoload :RGBA, File.join(File.dirname(__FILE__), 'color', 'rgba')
37
+ end
38
+ end
data/lib/iq-color.rb ADDED
@@ -0,0 +1 @@
1
+ require 'iq/color'
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'lib'))
2
+
3
+ require 'test/unit'
4
+ require 'rubygems'
5
+ begin
6
+ require 'redgreen'
7
+ rescue LoadError
8
+ end
9
+ require 'mocha'
10
+ require 'shoulda'
11
+
12
+ require 'iq/color'
13
+
14
+ class Class
15
+ def publicize_private_methods
16
+ saved_private_instance_methods = self.private_instance_methods
17
+ self.class_eval { public *saved_private_instance_methods }
18
+ yield self
19
+ self.class_eval { private *saved_private_instance_methods }
20
+ end
21
+
22
+ def publicize_protected_methods
23
+ saved_protected_instance_methods = self.protected_instance_methods
24
+ self.class_eval { public *saved_protected_instance_methods }
25
+ yield self
26
+ self.class_eval { protected *saved_protected_instance_methods }
27
+ end
28
+ end
@@ -0,0 +1,40 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'helper')
2
+
3
+ class IQ::ColorTest < Test::Unit::TestCase
4
+ context "from_css" do
5
+ should "raise when given non string value" do
6
+ not_a_string = stub
7
+ not_a_string.stubs(:is_a?).with(String).returns(false)
8
+ assert_raise(ArgumentError) { IQ::Color.from_css(not_a_string) }
9
+ end
10
+
11
+ should "delegate to rgb class for 3 digit hex values" do
12
+ IQ::Color::RGB.stubs(:from_css).with('#fed').returns('from rgb class')
13
+ assert_equal 'from rgb class', IQ::Color.from_css('#fed')
14
+ end
15
+
16
+ should "delegate to rgb class for 6 digit hex values" do
17
+ IQ::Color::RGB.stubs(:from_css).with('#ffeedd').returns('from rgb class')
18
+ assert_equal 'from rgb class', IQ::Color.from_css('#ffeedd')
19
+ end
20
+
21
+ should "delegate to rgb class for rgb notation" do
22
+ IQ::Color::RGB.stubs(:from_css).with('rgb(1,2,3)').returns('from rgb class')
23
+ assert_equal 'from rgb class', IQ::Color.from_css('rgb(1,2,3)')
24
+ end
25
+
26
+ should "delegate to rgba class for rgba notation" do
27
+ IQ::Color::RGBA.stubs(:from_css).with('rgba(1,2,3,0.8)').returns('from rgba class')
28
+ assert_equal 'from rgba class', IQ::Color.from_css('rgba(1,2,3,0.8)')
29
+ end
30
+
31
+ should "delegate to rgba class for transparent string" do
32
+ IQ::Color::RGBA.stubs(:from_css).with('transparent').returns('from rgba class')
33
+ assert_equal 'from rgba class', IQ::Color.from_css('transparent')
34
+ end
35
+
36
+ should "raise when unrecognised format" do
37
+ assert_raise(ArgumentError) { IQ::Color.from_css('nonsense') }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,215 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'helper')
2
+
3
+ class IQ::Color::RGBTest < Test::Unit::TestCase
4
+ context "class definition" do
5
+ should "inherit from base class" do
6
+ assert_equal IQ::Color::Base, IQ::Color::RGB.superclass
7
+ end
8
+ end
9
+
10
+ context "instance methods" do
11
+ context "initialize" do
12
+ context "red" do
13
+ should "raise when red value is not an integer" do
14
+ not_an_integer = stub_everything
15
+ not_an_integer.stubs(:is_a?).with(Integer).returns(false)
16
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
17
+ assert_raise(ArgumentError) do
18
+ IQ::Color::RGB.new(not_an_integer, mock_integer, mock_integer)
19
+ end
20
+ end
21
+
22
+ should "raise when red value is greater than 255" do
23
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
24
+ assert_raise(ArgumentError) do
25
+ IQ::Color::RGB.new(256, mock_integer, mock_integer)
26
+ end
27
+ end
28
+
29
+ should "raise when red value is less than zero" do
30
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
31
+ assert_raise(ArgumentError) do
32
+ IQ::Color::RGB.new(-1, mock_integer, mock_integer)
33
+ end
34
+ end
35
+
36
+ should "store red value in instance variable" do
37
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
38
+ assert_equal 123, IQ::Color::RGB.new(123, mock_integer, mock_integer).instance_variable_get('@red')
39
+ end
40
+ end
41
+
42
+ context "green" do
43
+ should "raise when green value is not an integer" do
44
+ not_an_integer = stub_everything
45
+ not_an_integer.stubs(:is_a?).with(Integer).returns(false)
46
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
47
+ assert_raise(ArgumentError) do
48
+ IQ::Color::RGB.new(mock_integer, not_an_integer, mock_integer)
49
+ end
50
+ end
51
+
52
+ should "raise when green value is greater than 255" do
53
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
54
+ assert_raise(ArgumentError) do
55
+ IQ::Color::RGB.new(mock_integer, 256, mock_integer)
56
+ end
57
+ end
58
+
59
+ should "raise when green value is less than zero" do
60
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
61
+ assert_raise(ArgumentError) do
62
+ IQ::Color::RGB.new(mock_integer, -1, mock_integer)
63
+ end
64
+ end
65
+
66
+ should "store green value in instance variable" do
67
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
68
+ assert_equal 123, IQ::Color::RGB.new(mock_integer, 123, mock_integer).instance_variable_get('@green')
69
+ end
70
+ end
71
+
72
+ context "blue" do
73
+ should "raise when blue value is not an integer" do
74
+ not_an_integer = stub_everything
75
+ not_an_integer.stubs(:is_a?).with(Integer).returns(false)
76
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
77
+ assert_raise(ArgumentError) do
78
+ IQ::Color::RGB.new(mock_integer, mock_integer, not_an_integer)
79
+ end
80
+ end
81
+
82
+ should "raise when blue value is greater than 255" do
83
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
84
+ assert_raise(ArgumentError) do
85
+ IQ::Color::RGB.new(mock_integer, mock_integer, 256)
86
+ end
87
+ end
88
+
89
+ should "raise when blue value is less than zero" do
90
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
91
+ assert_raise(ArgumentError) do
92
+ IQ::Color::RGB.new(mock_integer, mock_integer, -1)
93
+ end
94
+ end
95
+
96
+ should "store blue value in instance variable" do
97
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
98
+ assert_equal 123, IQ::Color::RGB.new(mock_integer, mock_integer, 123).instance_variable_get('@blue')
99
+ end
100
+ end
101
+ end
102
+
103
+ context "red" do
104
+ should "return value of instance variable" do
105
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
106
+ instance = IQ::Color::RGB.new(mock_integer, mock_integer, mock_integer)
107
+ instance.instance_variable_set '@red', 'the red'
108
+ assert_equal 'the red', instance.red
109
+ end
110
+ end
111
+
112
+ context "green" do
113
+ should "return value of instance variable" do
114
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
115
+ instance = IQ::Color::RGB.new(mock_integer, mock_integer, mock_integer)
116
+ instance.instance_variable_set '@green', 'the green'
117
+ assert_equal 'the green', instance.green
118
+ end
119
+ end
120
+
121
+ context "blue" do
122
+ should "return value of instance variable" do
123
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
124
+ instance = IQ::Color::RGB.new(mock_integer, mock_integer, mock_integer)
125
+ instance.instance_variable_set '@blue', 'the blue'
126
+ assert_equal 'the blue', instance.blue
127
+ end
128
+ end
129
+
130
+ context "to_css" do
131
+ should "return colour values as a six digit css hex string" do
132
+ mock_integer = stub_everything(:is_a? => true, :< => false, :> => false)
133
+ instance = IQ::Color::RGB.new(mock_integer, mock_integer, mock_integer)
134
+ instance.stubs(:red).returns(254)
135
+ instance.stubs(:green).returns(220)
136
+ instance.stubs(:blue).returns(186)
137
+ assert_equal '#fedcba', instance.to_css
138
+ end
139
+ end
140
+
141
+ context "class methods" do
142
+ context "from_css" do
143
+ should "raise when argument is not a string" do
144
+ not_a_string = stub_everything
145
+ not_a_string.stubs(:is_a?).with(String).returns(false)
146
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css(not_a_string) }
147
+ end
148
+
149
+ should "return new instance for 3 digit hex string" do
150
+ klass = IQ::Color::RGB
151
+ klass.stubs(:new).with(255, 238, 221).returns('the instance')
152
+ assert_equal 'the instance', klass.from_css('#fed')
153
+ end
154
+
155
+ should "ignore case when returning new instance for 3 digit hex string" do
156
+ klass = IQ::Color::RGB
157
+ klass.stubs(:new).with(255, 238, 221).returns('the instance')
158
+ assert_equal 'the instance', klass.from_css('#fED')
159
+ end
160
+
161
+ should "raise for malformed 3 digit hex string" do
162
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('#fzd') }
163
+ end
164
+
165
+ should "return new instance for 6 digit hex string" do
166
+ klass = IQ::Color::RGB
167
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
168
+ assert_equal 'the instance', klass.from_css('#fedcba')
169
+ end
170
+
171
+ should "ignore case when returning new instance for 6 digit hex string" do
172
+ klass = IQ::Color::RGB
173
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
174
+ assert_equal 'the instance', klass.from_css('#fedcba')
175
+ end
176
+
177
+ should "raise_for_malformed_6_digit_hex_string" do
178
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('#fzdcba') }
179
+ end
180
+
181
+ should "raise_given_hex_string_of_wrong_length" do
182
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('#febcdaf') }
183
+ end
184
+
185
+ should "return new instance for rgb notation string" do
186
+ klass = IQ::Color::RGB
187
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
188
+ assert_equal 'the instance', klass.from_css('rgb(254,220,186)')
189
+ end
190
+
191
+ should "allow spaces before and after values in rgb notation string" do
192
+ klass = IQ::Color::RGB
193
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
194
+ assert_equal 'the instance', klass.from_css('rgb( 254 , 220 , 186 )')
195
+ end
196
+
197
+ should "convert percentages in rgb notation to relevant rounded values" do
198
+ klass = IQ::Color::RGB
199
+ klass.stubs(:new).with(67, 38, 220).returns('the instance')
200
+ assert_equal 'the instance', klass.from_css('rgb(26%,15%,86%)')
201
+ end
202
+
203
+ should "accept fractional percentages in rgb notation" do
204
+ klass = IQ::Color::RGB
205
+ klass.stubs(:new).with(67, 39, 222).returns('the instance')
206
+ assert_equal 'the instance', klass.from_css('rgb(26.3%,15.2%,86.8%)')
207
+ end
208
+
209
+ should "raise when format is unrecognised" do
210
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('nonsense') }
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,302 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'helper')
2
+
3
+ class IQ::Color::RGBATest < Test::Unit::TestCase
4
+ context "class definition" do
5
+ should "inherit from rgb class" do
6
+ assert_equal IQ::Color::RGB, IQ::Color::RGBA.superclass
7
+ end
8
+ end
9
+
10
+ context "instance methods" do
11
+ context "initialize" do
12
+ context "red" do
13
+ should "raise when red value is not an integer" do
14
+ not_an_integer = stub_everything
15
+ not_an_integer.stubs(:is_a?).with(Integer).returns(false)
16
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
17
+ assert_raise(ArgumentError) do
18
+ IQ::Color::RGBA.new(not_an_integer, mock_number, mock_number, mock_number)
19
+ end
20
+ end
21
+
22
+ should "raise when red value is greater than 255" do
23
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
24
+ assert_raise(ArgumentError) do
25
+ IQ::Color::RGBA.new(256, mock_number, mock_number, mock_number)
26
+ end
27
+ end
28
+
29
+ should "raise when red value is less than zero" do
30
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
31
+ assert_raise(ArgumentError) do
32
+ IQ::Color::RGBA.new(-1, mock_number, mock_number, mock_number)
33
+ end
34
+ end
35
+
36
+ should "store red value in instance variable" do
37
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
38
+ assert_equal 123, IQ::Color::RGBA.new(
39
+ 123, mock_number, mock_number, mock_number
40
+ ).instance_variable_get('@red')
41
+ end
42
+ end
43
+
44
+ context "green" do
45
+ should "raise when green value is not an integer" do
46
+ not_an_integer = stub_everything
47
+ not_an_integer.stubs(:is_a?).with(Integer).returns(false)
48
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
49
+ assert_raise(ArgumentError) do
50
+ IQ::Color::RGBA.new(mock_number, not_an_integer, mock_number, mock_number)
51
+ end
52
+ end
53
+
54
+ should "raise when green value is greater than 255" do
55
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
56
+ assert_raise(ArgumentError) do
57
+ IQ::Color::RGBA.new(mock_number, 256, mock_number, mock_number)
58
+ end
59
+ end
60
+
61
+ should "raise when green value is less than zero" do
62
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
63
+ assert_raise(ArgumentError) do
64
+ IQ::Color::RGBA.new(mock_number, -1, mock_number, mock_number)
65
+ end
66
+ end
67
+
68
+ should "store green value in instance variable" do
69
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
70
+ assert_equal 123, IQ::Color::RGBA.new(
71
+ mock_number, 123, mock_number, mock_number
72
+ ).instance_variable_get('@green')
73
+ end
74
+ end
75
+
76
+ context "blue" do
77
+ should "raise when blue value is not an integer" do
78
+ not_an_integer = stub_everything
79
+ not_an_integer.stubs(:is_a?).with(Integer).returns(false)
80
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
81
+ assert_raise(ArgumentError) do
82
+ IQ::Color::RGBA.new(mock_number, mock_number, not_an_integer, mock_number)
83
+ end
84
+ end
85
+
86
+ should "raise when blue value is greater than 255" do
87
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
88
+ assert_raise(ArgumentError) do
89
+ IQ::Color::RGBA.new(mock_number, mock_number, 256, mock_number)
90
+ end
91
+ end
92
+
93
+ should "raise when blue value is less than zero" do
94
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
95
+ assert_raise(ArgumentError) do
96
+ IQ::Color::RGBA.new(mock_number, mock_number, -1, mock_number)
97
+ end
98
+ end
99
+
100
+ should "store blue value in instance variable" do
101
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
102
+ assert_equal 123, IQ::Color::RGBA.new(
103
+ mock_number, mock_number, 123, mock_number
104
+ ).instance_variable_get('@blue')
105
+ end
106
+ end
107
+
108
+ context "alpha" do
109
+ should "store alpha value of 1 when no forth argument supplied" do
110
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
111
+ assert_equal 1.0, IQ::Color::RGBA.new(mock_number, mock_number, mock_number).instance_variable_get('@alpha')
112
+ end
113
+
114
+ should "raise when alpha value is not an integer or float" do
115
+ not_an_integer_or_float = stub_everything
116
+ not_an_integer_or_float.stubs(:is_a?).with(Integer).returns(false)
117
+ not_an_integer_or_float.stubs(:is_a?).with(Float).returns(false)
118
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
119
+ assert_raise(ArgumentError) do
120
+ IQ::Color::RGBA.new(mock_number, mock_number, mock_number, not_an_integer_or_float)
121
+ end
122
+ end
123
+
124
+ should "raise when alpha value is greater than 1" do
125
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
126
+ assert_raise(ArgumentError) do
127
+ IQ::Color::RGBA.new(mock_number, mock_number, mock_number, 1.1)
128
+ end
129
+ end
130
+
131
+ should "raise when alpha value is less than zero" do
132
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
133
+ assert_raise(ArgumentError) do
134
+ IQ::Color::RGBA.new(mock_number, mock_number, mock_number, -0.1)
135
+ end
136
+ end
137
+
138
+ should "store alpha value as float in instance variable" do
139
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
140
+ the_alpha = stub_everything(:< => false, :> => false)
141
+ the_alpha.stubs(:is_a?).with(Integer).returns(true)
142
+ the_alpha.stubs(:to_f).returns('floatified value')
143
+ assert_equal 'floatified value', IQ::Color::RGBA.new(
144
+ mock_number, mock_number, mock_number, the_alpha
145
+ ).instance_variable_get('@alpha')
146
+ end
147
+ end
148
+ end
149
+
150
+ context "red" do
151
+ should "return value of instance variable" do
152
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
153
+ instance = IQ::Color::RGBA.new(mock_number, mock_number, mock_number, mock_number)
154
+ instance.instance_variable_set '@red', 'the red'
155
+ assert_equal 'the red', instance.red
156
+ end
157
+ end
158
+
159
+ context "green" do
160
+ should "return value of instance variable" do
161
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
162
+ instance = IQ::Color::RGBA.new(mock_number, mock_number, mock_number, mock_number)
163
+ instance.instance_variable_set '@green', 'the green'
164
+ assert_equal 'the green', instance.green
165
+ end
166
+ end
167
+
168
+ context "blue" do
169
+ should "return value of instance variable" do
170
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
171
+ instance = IQ::Color::RGBA.new(mock_number, mock_number, mock_number, mock_number)
172
+ instance.instance_variable_set '@blue', 'the blue'
173
+ assert_equal 'the blue', instance.blue
174
+ end
175
+ end
176
+
177
+ context "alpha" do
178
+ should "return value of instance variable" do
179
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
180
+ instance = IQ::Color::RGBA.new(mock_number, mock_number, mock_number, mock_number)
181
+ instance.instance_variable_set '@alpha', 'the alpha'
182
+ assert_equal 'the alpha', instance.alpha
183
+ end
184
+ end
185
+
186
+ context "to_css" do
187
+ should "return colour values as an rgba css string" do
188
+ mock_number = stub_everything(:is_a? => true, :< => false, :> => false)
189
+ instance = IQ::Color::RGBA.new(mock_number, mock_number, mock_number, mock_number)
190
+ instance.stubs(:red).returns(254)
191
+ instance.stubs(:green).returns(220)
192
+ instance.stubs(:blue).returns(186)
193
+ instance.stubs(:alpha).returns(0.4)
194
+ assert_equal 'rgba(254,220,186,0.4)', instance.to_css
195
+ end
196
+ end
197
+ end
198
+
199
+ context "class methods" do
200
+ context "from css" do
201
+ should "raise when argument is not a string" do
202
+ not_a_string = stub_everything
203
+ not_a_string.stubs(:is_a?).with(String).returns(false)
204
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css(not_a_string) }
205
+ end
206
+
207
+ should "return new instance for 3 digit hex string" do
208
+ klass = IQ::Color::RGB
209
+ klass.stubs(:new).with(255, 238, 221).returns('the instance')
210
+ assert_equal 'the instance', klass.from_css('#fed')
211
+ end
212
+
213
+ should "ignore case when returning new instance for 3 digit hex string" do
214
+ klass = IQ::Color::RGB
215
+ klass.stubs(:new).with(255, 238, 221).returns('the instance')
216
+ assert_equal 'the instance', klass.from_css('#fED')
217
+ end
218
+
219
+ should "raise for malformed 3 digit hex string" do
220
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('#fzd') }
221
+ end
222
+
223
+ should "return new instance for 6 digit hex string" do
224
+ klass = IQ::Color::RGB
225
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
226
+ assert_equal 'the instance', klass.from_css('#fedcba')
227
+ end
228
+
229
+ should "ignore case when returning new instance for 6 digit hex string" do
230
+ klass = IQ::Color::RGB
231
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
232
+ assert_equal 'the instance', klass.from_css('#fedcba')
233
+ end
234
+
235
+ should "raise for malformed 6 digit hex string" do
236
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('#fzdcba') }
237
+ end
238
+
239
+ should "raise given hex string of wrong length" do
240
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('#febcdaf') }
241
+ end
242
+
243
+ should "return new instance for rgb notation string" do
244
+ klass = IQ::Color::RGB
245
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
246
+ assert_equal 'the instance', klass.from_css('rgb(254,220,186)')
247
+ end
248
+
249
+ should "allow spaces before and after values in rgb notation string" do
250
+ klass = IQ::Color::RGB
251
+ klass.stubs(:new).with(254, 220, 186).returns('the instance')
252
+ assert_equal 'the instance', klass.from_css('rgb( 254 , 220 , 186 )')
253
+ end
254
+
255
+ should "convert percentages in rgb notation to relevant rounded values" do
256
+ klass = IQ::Color::RGB
257
+ klass.stubs(:new).with(67, 38, 220).returns('the instance')
258
+ assert_equal 'the instance', klass.from_css('rgb(26%,15%,86%)')
259
+ end
260
+
261
+ should "accept fractional percentages in rgb notation" do
262
+ klass = IQ::Color::RGB
263
+ klass.stubs(:new).with(67, 39, 222).returns('the instance')
264
+ assert_equal 'the instance', klass.from_css('rgb(26.3%,15.2%,86.8%)')
265
+ end
266
+
267
+ should "return new instance for rgba notation string" do
268
+ klass = IQ::Color::RGBA
269
+ klass.stubs(:new).with(254, 220, 186, 0.8).returns('the instance')
270
+ assert_equal 'the instance', klass.from_css('rgba(254,220,186,0.8)')
271
+ end
272
+
273
+ should "allow spaces before and after values in rgba notation string" do
274
+ klass = IQ::Color::RGBA
275
+ klass.stubs(:new).with(254, 220, 186, 0.8).returns('the instance')
276
+ assert_equal 'the instance', klass.from_css('rgba( 254 , 220 , 186 , 0.8 )')
277
+ end
278
+
279
+ should "convert percentages in rgba notation to relevant rounded values" do
280
+ klass = IQ::Color::RGBA
281
+ klass.stubs(:new).with(67, 38, 220, 0.8).returns('the instance')
282
+ assert_equal 'the instance', klass.from_css('rgba(26%,15%,86%,0.8)')
283
+ end
284
+
285
+ should "accept fractional percentages in rgba notation" do
286
+ klass = IQ::Color::RGBA
287
+ klass.stubs(:new).with(67, 39, 222, 0.8).returns('the instance')
288
+ assert_equal 'the instance', klass.from_css('rgba(26.3%,15.2%,86.8%,0.8)')
289
+ end
290
+
291
+ should "return transparent color for transparent string" do
292
+ klass = IQ::Color::RGBA
293
+ klass.stubs(:new).with(0, 0, 0, 0).returns('the instance')
294
+ assert_equal 'the instance', klass.from_css('transparent')
295
+ end
296
+
297
+ should "raise when format is unrecognised" do
298
+ assert_raise(ArgumentError) { IQ::Color::RGB.from_css('nonsense') }
299
+ end
300
+ end
301
+ end
302
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iq-color
3
+ version: !ruby/object:Gem::Version
4
+ hash: 63
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 2
10
+ version: 0.9.2
11
+ platform: ruby
12
+ authors:
13
+ - Jamie Hill
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-18 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: IQ::Color provides simple classes for representing colour values and the conversion to and from CSS3 strings.
23
+ email:
24
+ - jamie@soniciq.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - LICENSE
35
+ - README.rdoc
36
+ - Rakefile
37
+ - iq-color.gemspec
38
+ - lib/iq-color.rb
39
+ - lib/iq/color.rb
40
+ - lib/iq/color/base.rb
41
+ - lib/iq/color/rgb.rb
42
+ - lib/iq/color/rgba.rb
43
+ - lib/iq/color/version.rb
44
+ - test/helper.rb
45
+ - test/iq/color/color_test.rb
46
+ - test/iq/color/rgb_test.rb
47
+ - test/iq/color/rgba_test.rb
48
+ has_rdoc: true
49
+ homepage: http://github.com/soniciq/iq-color
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.7
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: A series of classes for handling color conversion.
82
+ test_files:
83
+ - test/helper.rb
84
+ - test/iq/color/color_test.rb
85
+ - test/iq/color/rgb_test.rb
86
+ - test/iq/color/rgba_test.rb