color 1.4.1 → 1.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/color/css.rb CHANGED
@@ -1,28 +1,7 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
12
-
13
- require 'color'
14
-
15
1
  # This namespace contains some CSS colour names.
16
2
  module Color::CSS
17
3
  # Returns the RGB colour for name or +nil+ if the name is not valid.
18
4
  def self.[](name)
19
- @colors[name.to_s.downcase.to_sym]
20
- end
21
-
22
- @colors = {}
23
- Color::RGB.constants.each do |const|
24
- next if const == "PDF_FORMAT_STR"
25
- next if const == "Metallic"
26
- @colors[const.downcase.to_sym] ||= Color::RGB.const_get(const)
5
+ Color::RGB.by_name(name) { nil }
27
6
  end
28
7
  end
@@ -1,57 +1,40 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
12
-
13
1
  # A colour object representing shades of grey. Used primarily in PDF
14
2
  # document creation.
15
3
  class Color::GrayScale
4
+ include Color
5
+
16
6
  # The format of a DeviceGrey colour for PDF. In color-tools 2.0 this will
17
7
  # be removed from this package and added back as a modification by the
18
8
  # PDF::Writer package.
19
9
  PDF_FORMAT_STR = "%.3f %s"
20
10
 
21
- # Creates a greyscale colour object from fractional values 0..1.
22
- #
23
- # Color::GreyScale.from_fraction(0.5)
24
- def self.from_fraction(g = 0)
25
- color = Color::GrayScale.new
26
- color.g = g
27
- color
28
- end
11
+ class << self
12
+ # Creates a greyscale colour object from fractional values 0..1.
13
+ #
14
+ # Color::GreyScale.from_fraction(0.5)
15
+ def from_fraction(g = 0, &block)
16
+ new(g, 1.0, &block)
17
+ end
29
18
 
30
- # Creates a greyscale colour object from percentages 0..100.
31
- #
32
- # Color::GrayScale.from_percent(50)
33
- def self.from_percent(g = 0)
34
- Color::GrayScale.new(g)
19
+ # Creates a greyscale colour object from percentages 0..100.
20
+ #
21
+ # Color::GrayScale.from_percent(50)
22
+ def from_percent(g = 0, &block)
23
+ new(g, &block)
24
+ end
35
25
  end
36
26
 
37
27
  # Creates a greyscale colour object from percentages 0..100.
38
28
  #
39
29
  # Color::GrayScale.new(50)
40
- def initialize(g = 0)
41
- @g = g / 100.0
30
+ def initialize(g = 0, radix = 100.0, &block) # :yields self:
31
+ @g = Color.normalize(g / radix)
32
+ block.call if block
42
33
  end
43
34
 
44
- # Compares the other colour to this one. The other colour will be
45
- # converted to GreyScale before comparison, so the comparison between a
46
- # GreyScale colour and a non-GreyScale colour will be approximate and
47
- # based on the other colour's #to_greyscale conversion. If there is no
48
- # #to_greyscale conversion, this will raise an exception. This will report
49
- # that two GreyScale values are equivalent if they are within
50
- # COLOR_TOLERANCE of each other.
51
- def ==(other)
52
- other = other.to_grayscale
53
- other.kind_of?(Color::GrayScale) and
54
- ((@g - other.g).abs <= Color::COLOR_TOLERANCE)
35
+ # Coerces the other Color object to grayscale.
36
+ def coerce(other)
37
+ other.to_grayscale
55
38
  end
56
39
 
57
40
  # Present the colour as a DeviceGrey fill colour string for PDF. This will
@@ -85,8 +68,8 @@ class Color::GrayScale
85
68
 
86
69
  # Present the colour as an RGBA (with alpha) HTML/CSS colour string (e.g.,
87
70
  # "rgb(0%, 50%, 100%, 1)").
88
- def css_rgba
89
- "rgba(%3.2f%%, %3.2f%%, %3.2f%%, %1.2f)" % [ gray, gray, gray, 1 ]
71
+ def css_rgba(alpha = 1)
72
+ "rgba(%3.2f%%, %3.2f%%, %3.2f%%, %1.2f)" % [ gray, gray, gray, alpha ]
90
73
  end
91
74
 
92
75
  # Present the colour as an HSL HTML/CSS colour string (e.g., "hsl(180,
@@ -182,10 +165,7 @@ class Color::GrayScale
182
165
  # The addition is done using the grayscale accessor methods to ensure a
183
166
  # valid colour in the result.
184
167
  def +(other)
185
- other = other.to_grayscale
186
- ng = self.dup
187
- ng.g += other.g
188
- ng
168
+ self.class.from_fraction(g + other.to_grayscale.g)
189
169
  end
190
170
 
191
171
  # Subtracts another colour to the current colour. The other colour will be
@@ -195,18 +175,23 @@ class Color::GrayScale
195
175
  # The subtraction is done using the grayscale accessor methods to ensure a
196
176
  # valid colour in the result.
197
177
  def -(other)
198
- other = other.to_grayscale
199
- ng = self.dup
200
- ng.g -= other.g
201
- ng
178
+ self + (-other)
202
179
  end
203
180
 
204
181
  def inspect
205
182
  "Gray [%.2f%%]" % [ gray ]
206
183
  end
207
- end
208
184
 
209
- module Color
210
- # A synonym for Color::GrayScale.
211
- GreyScale = GrayScale
185
+ def to_a
186
+ [ g ]
187
+ end
188
+
189
+ def -@
190
+ gs = self.dup
191
+ gs.instance_variable_set(:@g, -g)
192
+ gs
193
+ end
212
194
  end
195
+
196
+ # A synonym for Color::GrayScale.
197
+ Color::GreyScale = Color::GrayScale
data/lib/color/hsl.rb CHANGED
@@ -1,51 +1,30 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
1
+ # -*- ruby encoding: utf-8 -*-
12
2
 
13
3
  # An HSL colour object. Internally, the hue (#h), saturation (#s), and
14
4
  # luminosity/lightness (#l) values are dealt with as fractional values in
15
5
  # the range 0..1.
16
6
  class Color::HSL
7
+ include Color
8
+
17
9
  class << self
18
10
  # Creates an HSL colour object from fractional values 0..1.
19
- def from_fraction(h = 0.0, s = 0.0, l = 0.0)
20
- colour = Color::HSL.new
21
- colour.h = h
22
- colour.s = s
23
- colour.l = l
24
- colour
11
+ def from_fraction(h = 0.0, s = 0.0, l = 0.0, &block)
12
+ new(h, s, l, 1.0, 1.0, &block)
25
13
  end
26
14
  end
27
15
 
28
- # Compares the other colour to this one. The other colour will be
29
- # converted to HSL before comparison, so the comparison between a HSL
30
- # colour and a non-HSL colour will be approximate and based on the other
31
- # colour's #to_hsl conversion. If there is no #to_hsl conversion, this
32
- # will raise an exception. This will report that two HSL values are
33
- # equivalent if all component values are within Color::COLOR_TOLERANCE of
34
- # each other.
35
- def ==(other)
36
- other = other.to_hsl
37
- other.kind_of?(Color::HSL) and
38
- ((@h - other.h).abs <= Color::COLOR_TOLERANCE) and
39
- ((@s - other.s).abs <= Color::COLOR_TOLERANCE) and
40
- ((@l - other.l).abs <= Color::COLOR_TOLERANCE)
16
+ # Coerces the other Color object into HSL.
17
+ def coerce(other)
18
+ other.to_hsl
41
19
  end
42
20
 
43
21
  # Creates an HSL colour object from the standard values of degrees and
44
22
  # percentages (e.g., 145 deg, 30%, 50%).
45
- def initialize(h = 0, s = 0, l = 0)
46
- @h = h / 360.0
47
- @s = s / 100.0
48
- @l = l / 100.0
23
+ def initialize(h = 0, s = 0, l = 0, radix1 = 360.0, radix2 = 100.0, &block) # :yields self:
24
+ @h = Color.normalize(h / radix1)
25
+ @s = Color.normalize(s / radix2)
26
+ @l = Color.normalize(l / radix2)
27
+ block.call if block
49
28
  end
50
29
 
51
30
  # Present the colour as an HTML/CSS colour string.
@@ -63,8 +42,8 @@ class Color::HSL
63
42
  # Present the colour as an RGBA (with alpha) HTML/CSS colour string (e.g.,
64
43
  # "rgb(0%, 50%, 100%, 1)"). Note that this will perform a #to_rgb
65
44
  # operation using the default conversion formula.
66
- def css_rgba
67
- to_rgb.css_rgba
45
+ def css_rgba(alpha = 1)
46
+ to_rgb.css_rgba(alpha)
68
47
  end
69
48
 
70
49
  # Present the colour as an HSL HTML/CSS colour string (e.g., "hsl(180,
@@ -79,46 +58,30 @@ class Color::HSL
79
58
  "hsla(%3.2f, %3.2f%%, %3.2f%%, %3.2f)" % [ hue, saturation, luminosity, 1 ]
80
59
  end
81
60
 
82
- # Converting to HSL as adapted from Foley and Van-Dam from
83
- # http://www.bobpowell.net/RGBHSB.htm.
61
+ # Converting from HSL to RGB. As with all colour conversions, this is
62
+ # approximate at best. The code here is adapted from fvd and van Dam,
63
+ # originally found at [1] (implemented similarly at [2]).
84
64
  #
85
- # NOTE:
86
- # * If the colour's luminosity is near zero, the colour is always black.
87
- # * If the colour's luminosity is near one, the colour is always white.
88
- # * If the colour's saturation is near zero, the colour is always a shade
89
- # of grey and is based only on the luminosity of the colour.
65
+ # This simplifies the calculations with the following assumptions:
66
+ # - Luminance values <= 0 always translate to Color::RGB::Black.
67
+ # - Luminance values >= 1 always translate to Color::RGB::White.
68
+ # - Saturation values <= 0 always translate to a shade of gray using
69
+ # luminance as a percentage of gray.
90
70
  #
91
- def to_rgb(ignored = nil)
92
- return Color::RGB.new if Color.near_zero_or_less?(@l)
93
- return Color::RGB.new(0xff, 0xff, 0xff) if Color.near_one_or_more?(@l)
94
- return Color::RGB.from_fraction(@l, @l, @l) if Color.near_zero?(@s)
95
-
96
- # Is the value less than 0.5?
97
- if Color.near_zero_or_less?(@l - 0.5)
98
- tmp2 = @l * (1.0 + @s.to_f)
71
+ # [1] http://bobpowell.net/RGBHSB.aspx
72
+ # [2] http://support.microsoft.com/kb/29240
73
+ def to_rgb(*)
74
+ if Color.near_zero_or_less?(l)
75
+ Color::RGB::Black
76
+ elsif Color.near_one_or_more?(l)
77
+ Color::RGB::White
78
+ elsif Color.near_zero?(s)
79
+ Color::RGB.from_grayscale_fraction(l)
99
80
  else
100
- tmp2 = @l + @s - (@l * @s.to_f)
81
+ # Only needed for Ruby 1.8. For Ruby 1.9+, we can do:
82
+ # Color::RGB.new(*compute_fvd_rgb, 1.0)
83
+ Color::RGB.new(*(compute_fvd_rgb + [ 1.0 ]))
101
84
  end
102
- tmp1 = 2.0 * @l - tmp2
103
-
104
- tmp3 = [ @h + (1.0 / 3.0), @h, @h - (1.0 / 3.0) ]
105
-
106
- rgb = tmp3.map { |hue|
107
- hue += 1.0 if Color.near_zero_or_less?(hue)
108
- hue -= 1.0 if Color.near_one_or_more?(hue)
109
-
110
- if Color.near_zero_or_less?((6.0 * hue) - 1.0)
111
- tmp1 + ((tmp2 - tmp1) * hue * 6.0)
112
- elsif Color.near_zero_or_less?((2.0 * hue) - 1.0)
113
- tmp2
114
- elsif Color.near_zero_or_less?((3.0 * hue) - 2.0)
115
- tmp1 + (tmp2 - tmp1) * ((2 / 3.0) - hue) * 6.0
116
- else
117
- tmp1
118
- end
119
- }
120
-
121
- Color::RGB.from_fraction(*rgb)
122
85
  end
123
86
 
124
87
  # Converts to RGB then YIQ.
@@ -209,13 +172,69 @@ class Color::HSL
209
172
  # Mix the mask colour (which will be converted to an HSL colour) with the
210
173
  # current colour at the stated mix percentage as a decimal value.
211
174
  #
212
- # NOTE:: This differs from Color::RGB#mix_with.
175
+ # NOTE:: This differs from Color::RGB#mix_with.
213
176
  def mix_with(color, mix_percent = 0.5)
214
- color = color.to_hsl
215
- _h = ((color.h - self.h) * mix_percent) + self.h
216
- _s = ((color.s - self.s) * mix_percent) + self.s
217
- _l = ((color.l - self.l) * mix_percent) + self.l
177
+ v = to_a.zip(coerce(color).to_a).map { |(x, y)|
178
+ ((y - x) * mix_percent) + x
179
+ }
180
+ self.class.from_fraction(*v)
181
+ end
182
+
183
+ def to_a
184
+ [ h, s, l ]
185
+ end
186
+
187
+ private
188
+
189
+ # This algorithm calculates based on a mixture of the saturation and
190
+ # luminance, and then takes the RGB values from the hue + 1/3, hue, and
191
+ # hue - 1/3 positions in a circular representation of colour divided into
192
+ # four parts (confusing, I know, but it's the way that it works). See
193
+ # #hue_to_rgb for more information.
194
+ def compute_fvd_rgb
195
+ t1, t2 = fvd_mix_sat_lum
196
+ [ h + (1 / 3.0), h, h - (1 / 3.0) ].map { |v|
197
+ hue_to_rgb(rotate_hue(v), t1, t2)
198
+ }
199
+ end
218
200
 
219
- self.class.from_fraction(_h, _s, _l)
201
+ # Mix saturation and luminance for use in hue_to_rgb. The base value is
202
+ # different depending on whether luminance is <= 50% or > 50%.
203
+ def fvd_mix_sat_lum
204
+ t = if Color.near_zero_or_less?(l - 0.5)
205
+ l * (1.0 + s.to_f)
206
+ else
207
+ l + s - (l * s.to_f)
208
+ end
209
+ [ 2.0 * l - t, t ]
210
+ end
211
+
212
+ # In HSL, hues are referenced as degrees in a colour circle. The flow
213
+ # itself is endless; therefore, we can rotate around. The only thing our
214
+ # implementation restricts is that you should not be > 1.0.
215
+ def rotate_hue(h)
216
+ h += 1.0 if Color.near_zero_or_less?(h)
217
+ h -= 1.0 if Color.near_one_or_more?(h)
218
+ h
219
+ end
220
+
221
+ # We calculate the interaction of the saturation/luminance mix (calculated
222
+ # earlier) based on the position of the hue in the circular colour space
223
+ # divided into quadrants. Our hue range is [0, 1), not [0, 360º).
224
+ #
225
+ # - The first quadrant covers the first 60º [0, 60º].
226
+ # - The second quadrant covers the next 120º (60º, 180º].
227
+ # - The third quadrant covers the next 60º (180º, 240º].
228
+ # - The fourth quadrant covers the final 120º (240º, 360º).
229
+ def hue_to_rgb(h, t1, t2)
230
+ if Color.near_zero_or_less?((6.0 * h) - 1.0)
231
+ t1 + ((t2 - t1) * h * 6.0)
232
+ elsif Color.near_zero_or_less?((2.0 * h) - 1.0)
233
+ t2
234
+ elsif Color.near_zero_or_less?((3.0 * h) - 2.0)
235
+ t1 + (t2 - t1) * ((2 / 3.0) - h) * 6.0
236
+ else
237
+ t1
238
+ end
220
239
  end
221
240
  end
data/lib/color/palette.rb CHANGED
@@ -1,15 +1,3 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
12
-
13
1
  require 'color'
14
2
 
15
3
  module Color::Palette
@@ -1,15 +1,3 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
12
-
13
1
  require 'color/palette'
14
2
 
15
3
  # A class that can read an Adobe Color palette file (used for Photoshop
@@ -1,15 +1,3 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
12
-
13
1
  require 'color/palette'
14
2
 
15
3
  # A class that can read a GIMP (GNU Image Manipulation Program) palette file
@@ -1,15 +1,3 @@
1
- #--
2
- # Color
3
- # Colour management with Ruby
4
- # http://rubyforge.org/projects/color
5
- # Version 1.4.1
6
- #
7
- # Licensed under a MIT-style licence. See Licence.txt in the main
8
- # distribution for full licensing information.
9
- #
10
- # Copyright (c) 2005 - 2010 Austin Ziegler and Matt Lyon
11
- #++
12
-
13
1
  require 'color/palette'
14
2
 
15
3
  # Generates a monochromatic constrasting colour palette for background and
@@ -25,7 +13,7 @@ require 'color/palette'
25
13
  # against the background.
26
14
  class Color::Palette::MonoContrast
27
15
  # Hash of CSS background colour values.
28
- #
16
+ #
29
17
  # This is always 11 values:
30
18
  #
31
19
  # 0:: The starting colour.
@@ -33,7 +21,7 @@ class Color::Palette::MonoContrast
33
21
  # -1..-5:: Darker colours.
34
22
  attr_reader :background
35
23
  # Hash of CSS foreground colour values.
36
- #
24
+ #
37
25
  # This is always 11 values:
38
26
  #
39
27
  # 0:: The starting colour.
@@ -48,19 +36,17 @@ class Color::Palette::MonoContrast
48
36
  # the palette based on the base colours. The default value for this is 125
49
37
  # / 255.0. If this value is set to +nil+, it will be restored to the
50
38
  # default.
51
- attr_accessor :minimum_brightness_diff
52
- remove_method :minimum_brightness_diff= ;
39
+ attr_reader :minimum_brightness_diff
53
40
  def minimum_brightness_diff=(bd) #:nodoc:
54
- if bd.nil?
55
- @minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
56
- elsif bd > 1.0
57
- @minimum_brightness_diff = 1.0
58
- elsif bd < 0.0
59
- @minimum_brightness_diff = 0.0
60
- else
61
- @minimum_brightness_diff = bd
62
- end
63
-
41
+ @minimum_brightness_diff = if bd.nil?
42
+ DEFAULT_MINIMUM_BRIGHTNESS_DIFF
43
+ elsif bd > 1.0
44
+ 1.0
45
+ elsif bd < 0.0
46
+ 0.0
47
+ else
48
+ bd
49
+ end
64
50
  regenerate(@background[0], @foreground[0])
65
51
  end
66
52
 
@@ -69,18 +55,17 @@ class Color::Palette::MonoContrast
69
55
  # The minimum colour difference between the background and the foreground,
70
56
  # and must be between 0..3. Setting this value will regenerate the palette
71
57
  # based on the base colours. The default value for this is 500 / 255.0.
72
- attr_accessor :minimum_color_diff
73
- remove_method :minimum_color_diff= ;
74
- def minimum_color_diff=(cd) #:noco:
75
- if cd.nil?
76
- @minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF
77
- elsif cd > 3.0
78
- @minimum_color_diff = 3.0
79
- elsif cd < 0.0
80
- @minimum_color_diff = 0.0
81
- else
82
- @minimum_color_diff = cd
83
- end
58
+ attr_reader :minimum_color_diff
59
+ def minimum_color_diff=(cd) #:nodoc:
60
+ @minimum_color_diff = if cd.nil?
61
+ DEFAULT_MINIMUM_COLOR_DIFF
62
+ elsif cd > 3.0
63
+ 3.0
64
+ elsif cd < 0.0
65
+ 0.0
66
+ else
67
+ cd
68
+ end
84
69
  regenerate(@background[0], @foreground[0])
85
70
  end
86
71
 
@@ -88,7 +73,6 @@ class Color::Palette::MonoContrast
88
73
  def initialize(background, foreground = nil)
89
74
  @minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
90
75
  @minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF
91
-
92
76
  regenerate(background, foreground)
93
77
  end
94
78
 
@@ -160,7 +144,7 @@ class Color::Palette::MonoContrast
160
144
 
161
145
  # Returns the absolute difference between the brightness levels of two
162
146
  # colours. This will be a decimal value between 0 and 1. W3C accessibility
163
- # guidelines for colour contrast[http://www.w3.org/TR/AERT#color-contrast]
147
+ # guidelines for {colour contrast}[http://www.w3.org/TR/AERT#color-contrast]
164
148
  # suggest that this value be at least approximately 0.49 (125 / 255.0) for
165
149
  # proper contrast.
166
150
  def brightness_diff(c1, c2)
@@ -168,8 +152,8 @@ class Color::Palette::MonoContrast
168
152
  end
169
153
 
170
154
  # Returns the contrast between to colours, a decimal value between 0 and
171
- # 3. W3C accessibility guidelines for colour
172
- # contrast[http://www.w3.org/TR/AERT#color-contrast] suggest that this
155
+ # 3. W3C accessibility guidelines for {colour
156
+ # contrast}[http://www.w3.org/TR/AERT#color-contrast] suggest that this
173
157
  # value be at least approximately 1.96 (500 / 255.0) for proper contrast.
174
158
  def color_diff(c1, c2)
175
159
  r = (c1.r - c2.r).abs