A SassScript object representing a CSS color.
A color may be represented internally as RGBA, HSLA, or both. It’s originally represented as whatever its input is; if it’s created with RGB values, it’s represented as RGBA, and if it’s created with HSL values, it’s represented as HSLA. Once a property is accessed that requires the other representation — for example, {#red} for an HSL color — that component is calculated and cached.
The alpha channel of a color is independent of its RGB or HSL representation. It’s always stored, as 1 if nothing else is specified. If only the alpha channel is modified using {#with}, the cached RGB and HSL values are retained.
A hash from color names to `[red, green, blue]` value arrays.
A hash from `[red, green, blue]` value arrays to color names.
Constructs an RGB or HSL color object, optionally with an alpha channel.
The RGB values must be between 0 and 255. The saturation and lightness values must be between 0 and 100. The alpha value must be between 0 and 1.
@raise [Sass::SyntaxError] if any color value isn’t in the specified range
@overload initialize(attrs)
The attributes are specified as a hash.
This hash must contain either `:hue`, `:saturation`, and `:value` keys,
or `:red`, `:green`, and `:blue` keys.
It cannot contain both HSL and RGB keys.
It may also optionally contain an `:alpha` key.
@param attrs [{Symbol => Numeric}] A hash of color attributes to values
@raise [ArgumentError] if not enough attributes are specified,
or both RGB and HSL attributes are specified
@overload initialize(rgba)
The attributes are specified as an array.
This overload only supports RGB or RGBA colors.
@param rgba [Array<Numeric>] A three- or four-element array
of the red, green, blue, and optionally alpha values (respectively)
of the color
@raise [ArgumentError] if not enough attributes are specified
# File lib/sass/script/color.rb, line 71
71: def initialize(attrs, allow_both_rgb_and_hsl = false)
72: super(nil)
73:
74: if attrs.is_a?(Array)
75: unless (3..4).include?(attrs.size)
76: raise ArgumentError.new("Color.new(array) expects a three- or four-element array")
77: end
78:
79: red, green, blue = attrs[0...3].map {|c| c.to_i}
80: @attrs = {:red => red, :green => green, :blue => blue}
81: @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
82: else
83: attrs = attrs.reject {|k, v| v.nil?}
84: hsl = [:hue, :saturation, :lightness] & attrs.keys
85: rgb = [:red, :green, :blue] & attrs.keys
86: if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty?
87: raise ArgumentError.new("Color.new(hash) may not have both HSL and RGB keys specified")
88: elsif hsl.empty? && rgb.empty?
89: raise ArgumentError.new("Color.new(hash) must have either HSL or RGB keys specified")
90: elsif !hsl.empty? && hsl.size != 3
91: raise ArgumentError.new("Color.new(hash) must have all three HSL values specified")
92: elsif !rgb.empty? && rgb.size != 3
93: raise ArgumentError.new("Color.new(hash) must have all three RGB values specified")
94: end
95:
96: @attrs = attrs
97: @attrs[:hue] = 360 if @attrs[:hue]
98: @attrs[:alpha] ||= 1
99: end
100:
101: [:red, :green, :blue].each do |k|
102: next if @attrs[k].nil?
103: @attrs[k] = @attrs[k].to_i
104: next if (0..255).include?(@attrs[k])
105: raise Sass::SyntaxError.new("#{k.to_s.capitalize} value must be between 0 and 255")
106: end
107:
108: [:saturation, :lightness].each do |k|
109: next if @attrs[k].nil?
110: @attrs[k] = 0 if @attrs[k] < 0.00001 && @attrs[k] > 0.00001
111: @attrs[k] = 100 if @attrs[k] - 100 < 0.00001 && @attrs[k] - 100 > 0.00001
112: next if (0..100).include?(@attrs[k])
113: raise Sass::SyntaxError.new("#{k.to_s.capitalize} must be between 0 and 100")
114: end
115:
116: unless (0..1).include?(@attrs[:alpha])
117: raise Sass::SyntaxError.new("Alpha channel must between 0 and 1")
118: end
119: end
The alpha channel (opacity) of the color. This is 1 unless otherwise defined.
@return [Fixnum]
# File lib/sass/script/color.rb, line 173
173: def alpha
174: @attrs[:alpha]
175: end
Returns whether this color object is translucent; that is, whether the alpha channel is non-1.
@return [Boolean]
# File lib/sass/script/color.rb, line 181
181: def alpha?
182: alpha < 1
183: end
The blue component of the color.
@return [Fixnum]
# File lib/sass/script/color.rb, line 140
140: def blue
141: hsl_to_rgb!
142: @attrs[:blue]
143: end
The SassScript `/` operation. Its functionality depends on the type of its argument:
{Number} : Divides each of the RGB color channels by the number.
{Color} : Divides each of this color’s RGB color channels by the other color’s.
{Literal} : See {Literal#div}.
@param other [Literal] The right-hand side of the operator @return [Color] The resulting color @raise [Sass::SyntaxError] if `other` is a number with units
# File lib/sass/script/color.rb, line 346
346: def div(other)
347: if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
348: piecewise(other, :/)
349: else
350: super
351: end
352: end
The SassScript `==` operation. **Note that this returns a {Sass::Script::Bool} object, not a Ruby boolean**.
@param other [Literal] The right-hand side of the operator @return [Bool] True if this literal is the same as the other,
false otherwise
# File lib/sass/script/color.rb, line 219
219: def eq(other)
220: Sass::Script::Bool.new(
221: other.is_a?(Color) && rgb == other.rgb && alpha == other.alpha)
222: end
The green component of the color.
@return [Fixnum]
# File lib/sass/script/color.rb, line 132
132: def green
133: hsl_to_rgb!
134: @attrs[:green]
135: end
Returns the hue, saturation, and lightness components of the color.
@return [Array
hue, saturation, and lightness values (respectively) of the color
# File lib/sass/script/color.rb, line 208
208: def hsl
209: [hue, saturation, lightness].freeze
210: end
The hue component of the color.
@return [Numeric]
# File lib/sass/script/color.rb, line 148
148: def hue
149: rgb_to_hsl!
150: @attrs[:hue]
151: end
Returns a string representation of the color.
@return [String] The hex value
# File lib/sass/script/color.rb, line 390
390: def inspect
391: alpha? ? rgba_str : hex_str
392: end
The lightness component of the color.
@return [Numeric]
# File lib/sass/script/color.rb, line 164
164: def lightness
165: rgb_to_hsl!
166: @attrs[:lightness]
167: end
The SassScript `-` operation. Its functionality depends on the type of its argument:
{Number} : Subtracts the number from each of the RGB color channels.
{Color} : Subtracts each of the other color’s RGB color channels from this color’s.
{Literal} : See {Literal#minus}.
@param other [Literal] The right-hand side of the operator @return [Color] The resulting color @raise [Sass::SyntaxError] if `other` is a number with units
# File lib/sass/script/color.rb, line 303
303: def minus(other)
304: if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
305: piecewise(other, :-)
306: else
307: super
308: end
309: end
The SassScript `%` operation. Its functionality depends on the type of its argument:
{Number} : Takes each of the RGB color channels module the number.
{Color} : Takes each of this color’s RGB color channels modulo the other color’s.
@param other [Number, Color] The right-hand side of the operator @return [Color] The resulting color @raise [Sass::SyntaxError] if `other` is a number with units
# File lib/sass/script/color.rb, line 366
366: def mod(other)
367: if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
368: piecewise(other, :%)
369: else
370: raise NoMethodError.new(nil, :mod)
371: end
372: end
The SassScript `+` operation. Its functionality depends on the type of its argument:
{Number} : Adds the number to each of the RGB color channels.
{Color} : Adds each of the RGB color channels together.
{Literal} : See {Literal#plus}.
@param other [Literal] The right-hand side of the operator @return [Color] The resulting color @raise [Sass::SyntaxError] if `other` is a number with units
# File lib/sass/script/color.rb, line 280
280: def plus(other)
281: if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
282: piecewise(other, :+)
283: else
284: super
285: end
286: end
The red component of the color.
@return [Fixnum]
# File lib/sass/script/color.rb, line 124
124: def red
125: hsl_to_rgb!
126: @attrs[:red]
127: end
Returns the red, green, and blue components of the color.
@return [Array
values (respectively) of the color
# File lib/sass/script/color.rb, line 200
200: def rgb
201: [red, green, blue].freeze
202: end
The saturation component of the color.
@return [Numeric]
# File lib/sass/script/color.rb, line 156
156: def saturation
157: rgb_to_hsl!
158: @attrs[:saturation]
159: end
The SassScript `*` operation. Its functionality depends on the type of its argument:
{Number} : Multiplies the number by each of the RGB color channels.
{Color} : Multiplies each of the RGB color channels together.
@param other [Number, Color] The right-hand side of the operator @return [Color] The resulting color @raise [Sass::SyntaxError] if `other` is a number with units
# File lib/sass/script/color.rb, line 323
323: def times(other)
324: if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
325: piecewise(other, :*)
326: else
327: raise NoMethodError.new(nil, :times)
328: end
329: end
Returns a string representation of the color. This is usually the color’s hex value, but if the color has a name that’s used instead.
@return [String] The string representation
# File lib/sass/script/color.rb, line 379
379: def to_s(opts = {})
380: return rgba_str if alpha?
381: return smallest if options[:style] == :compressed
382: return HTML4_COLORS_REVERSE[rgb] if HTML4_COLORS_REVERSE[rgb]
383: hex_str
384: end
@deprecated This will be removed in version 3.2. @see #
# File lib/sass/script/color.rb, line 187
187: def value
188: Haml::Util.haml_warn DEPRECATION WARNING:The Sass::Script::Color #value attribute is deprecated and will beremoved in version 3.2. Use the #rgb attribute instead.
189: rgb
190: end
Returns a copy of this color with one or more channels changed. RGB or HSL colors may be changed, but not both at once.
For example:
Color.new([10, 20, 30]).with(:blue => 40)
#=> rgb(10, 40, 30)
Color.new([126, 126, 126]).with(:red => 0, :green => 255)
#=> rgb(0, 255, 126)
Color.new([255, 0, 127]).with(:saturation => 60)
#=> rgb(204, 51, 127)
Color.new([1, 2, 3]).with(:alpha => 0.4)
#=> rgba(1, 2, 3, 0.4)
@param attrs [{Symbol => Numeric}]
A map of channel names (`:red`, `:green`, `:blue`, `:hue`, `:saturation`, `:lightness`, or `:alpha`) to values
@return [Color] The new Color object @raise [ArgumentError] if both RGB and HSL keys are specified
# File lib/sass/script/color.rb, line 243
243: def with(attrs)
244: attrs = attrs.reject {|k, v| v.nil?}
245: hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty?
246: rgb = !([:red, :green, :blue] & attrs.keys).empty?
247: if hsl && rgb
248: raise ArgumentError.new("Color#with may not have both HSL and RGB keys specified")
249: end
250:
251: if hsl
252: [:hue, :saturation, :lightness].each {|k| attrs[k] ||= send(k)}
253: elsif rgb
254: [:red, :green, :blue].each {|k| attrs[k] ||= send(k)}
255: else
256: # If we're just changing the alpha channel,
257: # keep all the HSL/RGB stuff we've calculated
258: attrs = @attrs.merge(attrs)
259: end
260: attrs[:alpha] ||= alpha
261:
262: Color.new(attrs, :allow_both_rgb_and_hsl)
263: end
# File lib/sass/script/color.rb, line 407
407: def hex_str
408: red, green, blue = rgb.map { |num| num.to_s(16).rjust(2, '0') }
409: "##{red}#{green}#{blue}"
410: end
# File lib/sass/script/color.rb, line 431
431: def hsl_to_rgb!
432: return if @attrs[:red] && @attrs[:blue] && @attrs[:green]
433:
434: h = @attrs[:hue] / 360.0
435: s = @attrs[:saturation] / 100.0
436: l = @attrs[:lightness] / 100.0
437:
438: # Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
439: m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
440: m1 = l * 2 - m2
441: @attrs[:red], @attrs[:green], @attrs[:blue] = [
442: hue_to_rgb(m1, m2, h + 1.0/3),
443: hue_to_rgb(m1, m2, h),
444: hue_to_rgb(m1, m2, h - 1.0/3)
445: ].map {|c| (c * 0xff).round}
446: end
# File lib/sass/script/color.rb, line 448
448: def hue_to_rgb(m1, m2, h)
449: h += 1 if h < 0
450: h -= 1 if h > 1
451: return m1 + (m2 - m1) * h * 6 if h * 6 < 1
452: return m2 if h * 2 < 1
453: return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2
454: return m1
455: end
# File lib/sass/script/color.rb, line 412
412: def piecewise(other, operation)
413: other_num = other.is_a? Number
414: if other_num && !other.unitless?
415: raise Sass::SyntaxError.new("Cannot add a number with units (#{other}) to a color (#{self}).")
416: end
417:
418: result = []
419: for i in (0...3)
420: res = rgb[i].send(operation, other_num ? other.value : other.rgb[i])
421: result[i] = [ [res, 255].min, 0 ].max
422: end
423:
424: if !other_num && other.alpha != alpha
425: raise Sass::SyntaxError.new("Alpha channels must be equal: #{self} #{operation} #{other}")
426: end
427:
428: with(:red => result[0], :green => result[1], :blue => result[2])
429: end
# File lib/sass/script/color.rb, line 457
457: def rgb_to_hsl!
458: return if @attrs[:hue] && @attrs[:saturation] && @attrs[:lightness]
459: r, g, b = [:red, :green, :blue].map {|k| @attrs[k] / 255.0}
460:
461: # Algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
462: max = [r, g, b].max
463: min = [r, g, b].min
464: d = max - min
465:
466: h =
467: case max
468: when min; 0
469: when r; 60 * (g-b)/d
470: when g; 60 * (b-r)/d + 120
471: when b; 60 * (r-g)/d + 240
472: end
473:
474: l = (max + min)/2.0
475:
476: s =
477: if max == min
478: 0
479: elsif l < 0.5
480: d/(2*l)
481: else
482: d/(2 - 2*l)
483: end
484:
485: @attrs[:hue] = h % 360
486: @attrs[:saturation] = s * 100
487: @attrs[:lightness] = l * 100
488: end
# File lib/sass/script/color.rb, line 403
403: def rgba_str
404: "rgba(#{rgb.join(', ')}, #{alpha % 1 == 0.0 ? alpha.to_i : alpha})"
405: end
# File lib/sass/script/color.rb, line 396
396: def smallest
397: small_hex_str = hex_str.gsub(/^#(.)\11((.)\22((.)\33$$/, '#\1\2\3')
398: return small_hex_str unless (color = HTML4_COLORS_REVERSE[rgb]) &&
399: color.size <= small_hex_str.size
400: return color
401: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.