Class: StyleTrain::Color

Inherits:
Object
  • Object
show all
Defined in:
lib/style_train/color.rb

Defined Under Namespace

Classes: AutodetectionError, ByteError, KeywordError, PercentageError, RatioError

Constant Summary collapse

COMPARE_TOLERANCE =

COMPARITORS ——————————————————

0.001
COLDEST_HUE =
240/360.0
WARMEST_HUE =
0.0
KEYWORD_MAP =
{
   :aliceblue	=>	[240, 248, 255],
	 	:antiquewhite	=>	[250, 235, 215],
	 	:aqua	=>	[0, 255, 255],
	 	:aquamarine	=>	[127, 255, 212],
	 	:azure	=>	[240, 255, 255],
	 	:beige	=>	[245, 245, 220],
	 	:bisque	=>	[255, 228, 196],
	 	:black	=>	[0, 0, 0],
	 	:blanchedalmond	=>	[255, 235, 205],
	 	:blue	=>	[0, 0, 255],
	 	:blueviolet	=>	[138, 43, 226],
	 	:brown	=>	[165, 42, 42],
	 	:burlywood	=>	[222, 184, 135],
	 	:cadetblue	=>	[95, 158, 160],
	 	:chartreuse	=>	[127, 255, 0],
	 	:chocolate	=>	[210, 105, 30],
	 	:coral	=>	[255, 127, 80],
	 	:cornflowerblue	=>	[100, 149, 237],
	 	:cornsilk	=>	[255, 248, 220],
	 	:crimson	=>	[220, 20, 60],
	 	:cyan	=>	[0, 255, 255],
	 	:darkblue	=>	[0, 0, 139],
	 	:darkcyan	=>	[0, 139, 139],
	 	:darkgoldenrod	=>	[184, 134, 11],
	 	:darkgray	=>	[169, 169, 169],
	 	:darkgreen	=>	[0, 100, 0],
	 	:darkgrey	=>	[169, 169, 169],
	 	:darkkhaki	=>	[189, 183, 107],
	 	:darkmagenta	=>	[139, 0, 139],
	 	:darkolivegreen	=>	[85, 107, 47],
	 	:darkorange	=>	[255, 140, 0],
	 	:darkorchid	=>	[153, 50, 204],
	 	:darkred	=>	[139, 0, 0],
	 	:darksalmon	=>	[233, 150, 122],
	 	:darkseagreen	=>	[143, 188, 143],
	 	:darkslateblue	=>	[72, 61, 139],
	 	:darkslategray	=>	[47, 79, 79],
	 	:darkslategrey	=>	[47, 79, 79],
	 	:darkturquoise	=>	[0, 206, 209],
	 	:darkviolet	=>	[148, 0, 211],
	 	:deeppink	=>	[255, 20, 147],
	 	:deepskyblue	=>	[0, 191, 255],
	 	:dimgray	=>	[105, 105, 105],
	 	:dimgrey	=>	[105, 105, 105],
	 	:dodgerblue	=>	[30, 144, 255],
	 	:firebrick	=>	[178, 34, 34],
	 	:floralwhite	=>	[255, 250, 240],
	 	:forestgreen	=>	[34, 139, 34],
	 	:fuchsia	=>	[255, 0, 255],
	 	:gainsboro	=>	[220, 220, 220],
	 	:ghostwhite	=>	[248, 248, 255],
	 	:gold	=>	[255, 215, 0],
	 	:goldenrod	=>	[218, 165, 32],
	 	:gray	=>	[128, 128, 128],
	 	:green	=>	[0, 128, 0],
	 	:greenyellow	=>	[173, 255, 47],
	 	:grey	=>	[128, 128, 128],
	 	:honeydew	=>	[240, 255, 240],
	 	:hotpink	=>	[255, 105, 180],
	 	:indianred	=>	[205, 92, 92],
	 	:indigo	=>	[75, 0, 130],
	 	:ivory	=>	[255, 255, 240],
	 	:khaki	=>	[240, 230, 140],
	 	:lavender	=>	[230, 230, 250],
	 	:lavenderblush	=>	[255, 240, 245],
	 	:lawngreen	=>	[124, 252, 0],
	 	:lemonchiffon	=>	[255, 250, 205],
	 	:lightblue	=>	[173, 216, 230],
	 	:lightcoral	=>	[240, 128, 128],
	 	:lightcyan	=>	[224, 255, 255],
	 	:lightgoldenrodyellow	=>	[250, 250, 210],
	 	:lightgray	=>	[211, 211, 211],
	 	:lightgreen	=>	[144, 238, 144],
	 	:lightgrey	=>	[211, 211, 211],
	 	:lightpink	=>	[255, 182, 193],
	 	:lightsalmon	=>	[255, 160, 122],
	 	:lightseagreen	=>	[32, 178, 170],
	 	:lightskyblue	=>	[135, 206, 250],
	 	:lightslategray	=>	[119, 136, 153],
	 	:lightslategrey	=>	[119, 136, 153],
	 	:lightsteelblue	=>	[176, 196, 222],
	 	:lightyellow	=>	[255, 255, 224],
	 	:lime	=>	[0, 255, 0],
	 	:limegreen	=>	[50, 205, 50],
	 	:linen	=>	[250, 240, 230],
	 	:magenta	=>	[255, 0, 255],
	 	:maroon	=>	[128, 0, 0],
	 	:mediumaquamarine	=>	[102, 205, 170],
	 	:mediumblue	=>	[0, 0, 205],
	 	:mediumorchid	=>	[186, 85, 211],
	 	:mediumpurple	=>	[147, 112, 219],
	 	:mediumseagreen	=>	[60, 179, 113],
	 	:mediumslateblue	=>	[123, 104, 238],
	 	:mediumspringgreen	=>	[0, 250, 154],
	 	:mediumturquoise	=>	[72, 209, 204],
	 	:mediumvioletred	=>	[199, 21, 133],
	 	:midnightblue	=>	[25, 25, 112],
	 	:mintcream	=>	[245, 255, 250],
	 	:mistyrose	=>	[255, 228, 225],
	 	:moccasin	=>	[255, 228, 181],
	 	:navajowhite	=>	[255, 222, 173],
	 	:navy	=>	[0, 0, 128],
	 	:oldlace	=>	[253, 245, 230],
	 	:olive	=>	[128, 128, 0],
	 	:olivedrab	=>	[107, 142, 35],
	 	:orange	=>	[255, 165, 0],
	 	:orangered	=>	[255, 69, 0],
	 	:orchid	=>	[218, 112, 214],
	 	:palegoldenrod	=>	[238, 232, 170],
	 	:palegreen	=>	[152, 251, 152],
	 	:paleturquoise	=>	[175, 238, 238],
	 	:palevioletred	=>	[219, 112, 147],
	 	:papayawhip	=>	[255, 239, 213],
	 	:peachpuff	=>	[255, 218, 185],
	 	:peru	=>	[205, 133, 63],
	 	:pink	=>	[255, 192, 203],
	 	:plum	=>	[221, 160, 221],
	 	:powderblue	=>	[176, 224, 230],
	 	:purple	=>	[128, 0, 128],
	 	:red	=>	[255, 0, 0],
	 	:rosybrown	=>	[188, 143, 143],
	 	:royalblue	=>	[65, 105, 225],
	 	:saddlebrown	=>	[139, 69, 19],
	 	:salmon	=>	[250, 128, 114],
	 	:sandybrown	=>	[244, 164, 96],
	 	:seagreen	=>	[46, 139, 87],
	 	:seashell	=>	[255, 245, 238],
	 	:sienna	=>	[160, 82, 45],
	 	:silver	=>	[192, 192, 192],
	 	:skyblue	=>	[135, 206, 235],
	 	:slateblue	=>	[106, 90, 205],
	 	:slategray	=>	[112, 128, 144],
	 	:slategrey	=>	[112, 128, 144],
	 	:snow	=>	[255, 250, 250],
	 	:springgreen	=>	[0, 255, 127],
	 	:steelblue	=>	[70, 130, 180],
	 	:tan	=>	[210, 180, 140],
	 	:teal	=>	[0, 128, 128],
	 	:thistle	=>	[216, 191, 216],
	 	:tomato	=>	[255, 99, 71],
	 	:turquoise	=>	[64, 224, 208],
	 	:violet	=>	[238, 130, 238],
	 	:wheat	=>	[245, 222, 179],
	 	:white	=>	[255, 255, 255],
	 	:whitesmoke	=>	[245, 245, 245],
	 	:yellow	=>	[255, 255, 0],
	 	:yellowgreen	=>	[154, 205, 50]
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Color

Returns a new instance of Color.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/style_train/color.rb', line 8

def initialize(*args)
  if type = args.last.is_a?(Hash) && args.last[:type]
    build_for_type(type, args)
  else
    autodetect(args)
  end
  
  if non_null?
    if (opts = args.last) && args.last.is_a?(Hash)
      self.alpha = opts[:alpha]
      self.background = opts[:background] if opts[:background]
    end
  end
  self.alpha = 1.0 if alpha.nil? && non_null?
end

Instance Attribute Details

#alphaObject

Returns the value of attribute alpha.



5
6
7
# File 'lib/style_train/color.rb', line 5

def alpha
  @alpha
end

#bObject

Returns the value of attribute b.



3
4
5
# File 'lib/style_train/color.rb', line 3

def b
  @b
end

#gObject

Returns the value of attribute g.



3
4
5
# File 'lib/style_train/color.rb', line 3

def g
  @g
end

#hObject

Returns the value of attribute h.



3
4
5
# File 'lib/style_train/color.rb', line 3

def h
  @h
end

#hexObject

Returns the value of attribute hex.



3
4
5
# File 'lib/style_train/color.rb', line 3

def hex
  @hex
end

#hex_6Object

Returns the value of attribute hex_6.



3
4
5
# File 'lib/style_train/color.rb', line 3

def hex_6
  @hex_6
end

#lObject

Returns the value of attribute l.



3
4
5
# File 'lib/style_train/color.rb', line 3

def l
  @l
end

#mix_ratioObject



524
525
526
527
528
# File 'lib/style_train/color.rb', line 524

def mix_ratio
  ratio = @mix_ratio
  self.mix_ratio = nil
  ratio
end

#rObject

Returns the value of attribute r.



3
4
5
# File 'lib/style_train/color.rb', line 3

def r
  @r
end

#sObject

Returns the value of attribute s.



3
4
5
# File 'lib/style_train/color.rb', line 3

def s
  @s
end

#typeObject

Returns the value of attribute type.



3
4
5
# File 'lib/style_train/color.rb', line 3

def type
  @type
end

Class Method Details

.blend_alphas(first, second) ⇒ Object



534
535
536
537
538
# File 'lib/style_train/color.rb', line 534

def self.blend_alphas(first, second)
  base, blender = first > second ? [first, second] : [second, first]
  difference = 1.0 - base
  base + difference * blender
end

.degree_regexObject



201
202
203
# File 'lib/style_train/color.rb', line 201

def self.degree_regex
  /degrees$/
end

.mix(value_1, value_2, ratio) ⇒ Object



530
531
532
# File 'lib/style_train/color.rb', line 530

def self.mix(value_1, value_2, ratio)
  value_1*(ratio) + value_2*(1-ratio)
end

.normalize_byte(value) ⇒ Object

Raises:



205
206
207
208
# File 'lib/style_train/color.rb', line 205

def self.normalize_byte(value)
  raise ByteError  if value > 255 || value < 0
  value
end

.normalize_degrees(value) ⇒ Object



196
197
198
199
# File 'lib/style_train/color.rb', line 196

def self.normalize_degrees(value)
  return nil if value.is_a?(String) && !value.match(degree_regex)
  (value.to_i % 360)/360.0
end

.normalize_for_hsl(value) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/style_train/color.rb', line 128

def self.normalize_for_hsl(value)
  if value.is_a?(String)
    normalize_percentage(value)/100.0 if value.match(/%$/)
  elsif value.is_a?(Float)
    normalize_ratio(value)
  else # integer
    normalize_byte(value)/255.0
  end
end

.normalize_for_rgb(value) ⇒ Object

CLASS LEVEL VALUE NORMALIZERS ———————————————–



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/style_train/color.rb', line 167

def self.normalize_for_rgb(value)
  if value.is_a?(String)
    if value.match(percentage_regex)
      normalize_percentage(value)/100.0
    elsif value.match(degree_regex)
      return nil
    else
      normalize_byte(value)/255.0
    end
  elsif value.is_a?(Float)
    normalize_ratio(value)
  else # integer
    normalize_byte(value)/255.0
  end
end

.normalize_hex(hex) ⇒ Object



220
221
222
223
224
225
226
227
228
229
# File 'lib/style_train/color.rb', line 220

def self.normalize_hex( hex ) 
  expanded = ""
  if hex.size == 3
    hex.each_char{|c| expanded << c*2}
  else
    expanded = hex
  end
  
  "0x#{expanded}".to_i(16)       
end

.normalize_hue(value) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/style_train/color.rb', line 114

def self.normalize_hue(value)
  if value.is_a?(String) 
    if value.match(/degrees$/)
      normalize_degrees(value)
    else 
      normalize_percentage(value) / 100.0
    end
  elsif value.is_a?(Float)
    normalize_ratio(value)
  else
    normalize_degrees(value) # hue does not come it byte values
  end
end

.normalize_percentage(value) ⇒ Object

Raises:



183
184
185
186
187
188
189
190
# File 'lib/style_train/color.rb', line 183

def self.normalize_percentage(value)
  if value.class == String && value.match(percentage_regex)
    value = $1
  end
  value = value.to_f
  raise PercentageError  if value > 100.0 || value < 0.0 
  value
end

.normalize_ratio(value) ⇒ Object

Raises:



210
211
212
213
# File 'lib/style_train/color.rb', line 210

def self.normalize_ratio(value)
  raise RatioError if value > 1 || value < 0
  value
end

.percentage_regexObject



192
193
194
# File 'lib/style_train/color.rb', line 192

def self.percentage_regex
  /^([\d.]*)%$/
end

.percentage_to_byte(value) ⇒ Object



231
232
233
# File 'lib/style_train/color.rb', line 231

def self.percentage_to_byte(value)
  (normalize_percentage(value) * 2.55 ).round
end

.ratio_to_byte(value) ⇒ Object

Raises:



215
216
217
218
# File 'lib/style_train/color.rb', line 215

def self.ratio_to_byte(value)
  raise RatioError if value < 0 || value > 1.0
  percentage_to_byte(value*100)
end

.render_asObject



603
604
605
# File 'lib/style_train/color.rb', line 603

def self.render_as
  @render_as || :hex
end

.render_as=(value) ⇒ Object



607
608
609
# File 'lib/style_train/color.rb', line 607

def self.render_as=(value)
  @render_as = value
end

Instance Method Details

#==(other) ⇒ Object



261
262
263
264
# File 'lib/style_train/color.rb', line 261

def ==(other)
  self =~ other &&
  self.alpha == other.alpha
end

#===(other) ⇒ Object



266
267
268
# File 'lib/style_train/color.rb', line 266

def ===(other)
  self.object_id == other.object_id
end

#=~(other) ⇒ Object



270
271
272
273
274
# File 'lib/style_train/color.rb', line 270

def =~(other)
  (self.r - other.r).abs < COMPARE_TOLERANCE &&
  (self.g - other.g).abs < COMPARE_TOLERANCE&&
  (self.b - other.b).abs < COMPARE_TOLERANCE
end

#autodetect(args) ⇒ Object



48
49
50
51
52
53
54
# File 'lib/style_train/color.rb', line 48

def autodetect(args)
  build_transparent(args) ||
  build_keyword(args) ||
  build_hex(args) ||
  build_rgb(args) ||
  build_hsl(args) || raise( AutodetectionError )
end

#backgroundObject



254
255
256
# File 'lib/style_train/color.rb', line 254

def background
  @background || self.class.new(:white) unless type == :transparent
end

#background=(value) ⇒ Object



246
247
248
249
250
251
252
# File 'lib/style_train/color.rb', line 246

def background=(value)
  @background = if value.is_a?(self.class)
    value
  else
    self.class.new(*value)
  end
end

#build_for_type(type, args) ⇒ Object

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/style_train/color.rb', line 32

def build_for_type(type, args)
  self.type = type
  color = if type == :transparent
    build_transparent(args)
  elsif type == :keyword
    build_keyword(args)
  elsif type == :hex
    build_hex(args)
  elsif type == :rgb
    build_rgb(args)
  elsif type == :hsl
    build_hsl(args)
  end
  raise ArgumentError, "Unable to build a color of type #{type}, with arguments: #{args.inspect}" unless color
end

#build_hex(args) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/style_train/color.rb', line 76

def build_hex(args)
  if args.size < 3 && args.first.to_s.match(/^#?([a-f0-9]{3}|[a-f0-9]{6})$/i)
    self.type = :hex
    self.hex = "#{$1}"
    self.hex_6 = self.class.normalize_hex(hex)
    self.r = ((self.hex_6 / 0x10000) & 0xff) / 255.0
    self.g = ((self.hex_6 / 0x100) & 0xff) / 255.0
    self.b = (self.hex_6  & 0xff) /255.0
    self
  end
end

#build_hsl(args) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/style_train/color.rb', line 100

def build_hsl(args)
  array = args[0..2].compact
  hue = self.class.normalize_hue(array.first) rescue nil
  return nil unless array.size == 3 && hue
  
  self.type = :hsl
  self.h = hue
  self.s = self.class.normalize_for_hsl(array[1])
  self.l = self.class.normalize_for_hsl(array[2])
  build_rgb_from_hsl
  
  self
end

#build_keyword(args) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/style_train/color.rb', line 65

def build_keyword( args )
  if (color = args.first).is_a?(Symbol)
    self.type = :keyword
    raise KeywordError, "Color #{color.inspect} not found as a keyword" unless rgb = KEYWORD_MAP[color]
    self.r = rgb[0]/255.0
    self.g = rgb[1]/255.0
    self.b = rgb[2]/255.0
    self 
  end
end

#build_rgb(args) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/style_train/color.rb', line 88

def build_rgb(args)
  array = args[0..2].compact
  first_value = self.class.normalize_for_rgb(array.first) rescue nil
  return nil unless array.size == 3 && first_value
  
  self.type = :rgb
  self.r = first_value
  self.g = self.class.normalize_for_rgb(array[1])
  self.b = self.class.normalize_for_rgb(array[2])
  self
end

#build_rgb_from_hslObject



138
139
140
141
142
# File 'lib/style_train/color.rb', line 138

def build_rgb_from_hsl
  self.r = hsl_value_to_rgb( h + 1/3.0 )
  self.g = hsl_value_to_rgb( h )
  self.b = hsl_value_to_rgb( h - 1/3.0 )
end

#build_transparent(args) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/style_train/color.rb', line 56

def build_transparent( args )
  if [:transparent, 'transparent'].include?(args.first)
    self.type = :transparent
    self.r = self.g = self.b = 0
    self.alpha = 0.0
    self
  end 
end

#complimentObject



413
414
415
# File 'lib/style_train/color.rb', line 413

def compliment
  rotate(0.5)
end

#cooler(value = 10.degrees) ⇒ Object



470
471
472
473
# File 'lib/style_train/color.rb', line 470

def cooler(value=10.degrees)
  color = self.dup
  color.cooler!(value)
end

#cooler!(value = 10.degrees) ⇒ Object



455
456
457
458
459
460
461
462
463
# File 'lib/style_train/color.rb', line 455

def cooler!(value=10.degrees)
  rotate_in_temperature!(value) do |v|
    new_h = if h < COLDEST_HUE
      [COLDEST_HUE, (h + v)].min.abs
    else
      [COLDEST_HUE, (h - v)].max.abs
    end
  end
end

#darken(value = 0.1) ⇒ Object



365
366
367
368
# File 'lib/style_train/color.rb', line 365

def darken(value=0.1)
  color = self.dup
  color.darken!(value)
end

#darken!(value = 0.1) ⇒ Object



370
371
372
# File 'lib/style_train/color.rb', line 370

def darken!(value=0.1)
  shift!(value) { |v| self.l = [0.0, l - v].max }
end

#dial(divisions = 3, offset = 0.0) ⇒ Object



417
418
419
420
421
422
423
424
425
426
# File 'lib/style_train/color.rb', line 417

def dial(divisions=3, offset = 0.0)
  divisions = divisions.to_i
  offset = self.class.normalize_hue(offset)
  set = []
  (1..divisions).each do |n|
    amount = (offset + (n-1)/divisions.to_f)%1
    set << rotate(amount)
  end
  set
end

#dull(value = 0.1) ⇒ Object Also known as: desaturate



383
384
385
386
# File 'lib/style_train/color.rb', line 383

def dull(value=0.1)
  color = self.dup
  color.dull!(value)
end

#dull!(value = 0.1) ⇒ Object Also known as: desaturate!



388
389
390
# File 'lib/style_train/color.rb', line 388

def dull!(value=0.1)
  shift!(value) { |v| self.s = [0.0, s - v].max }
end

#flattenObject



514
515
516
517
# File 'lib/style_train/color.rb', line 514

def flatten
  background.alpha = 1.0
  background.layer(self)
end

#hsl_median_1Object



162
163
164
# File 'lib/style_train/color.rb', line 162

def hsl_median_1
  l*2-hsl_median_2
end

#hsl_median_2Object



158
159
160
# File 'lib/style_train/color.rb', line 158

def hsl_median_2
  l <= 0.5 ? l*(s+1) : l+s-l*s
end

#hsl_to_rgbObject



333
334
335
336
337
338
# File 'lib/style_train/color.rb', line 333

def hsl_to_rgb
  self.hex = nil
  self.hex_6 = nil
  build_rgb_from_hsl
  self
end

#hsl_value_to_rgb(value = [h,s,l]) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/style_train/color.rb', line 144

def hsl_value_to_rgb( value=[h,s,l] )
  value = value + 1 if value < 0 
  value = value - 1 if value > 1
  if value * 6 < 1
    hsl_median_1 + (hsl_median_2 - hsl_median_1)*value*6 
  elsif value * 2 < 1
    hsl_median_2
  elsif value * 3 < 2
    hsl_median_1 + (hsl_median_2 - hsl_median_1)*(2/3.0 - value)*6
  else
    hsl_median_1
  end
end

#inspectObject

RENDERING —————————————————–



542
543
544
# File 'lib/style_train/color.rb', line 542

def inspect
  "#<#{self.class}:#{self.object_id} @alpha=#{self.alpha} @r=#{self.r} @g=#{self.g} @b=#{self.b}>"
end

#layer(other) ⇒ Object



491
492
493
494
495
496
497
498
499
500
# File 'lib/style_train/color.rb', line 491

def layer(other)
  color = self.dup
  ratio = 1 - other.alpha
  color.r = self.class.mix(color.r, other.r, ratio)
  color.g = self.class.mix(color.g, other.g, ratio)
  color.b = self.class.mix(color.b, other.b, ratio)
  color.alpha = self.class.blend_alphas( color.alpha, other.alpha ) 
  
  color
end

#lighten(value = 0.1) ⇒ Object



356
357
358
359
# File 'lib/style_train/color.rb', line 356

def lighten(value=0.1)
  color = self.dup
  color.lighten!(value)
end

#lighten!(value = 0.1) ⇒ Object



361
362
363
# File 'lib/style_train/color.rb', line 361

def lighten!(value=0.1)
  shift!(value) {|v| self.l = [1.0, l + v].min }
end

#mix(other, ratio = nil) ⇒ Object

COMBINING COLORS ——————————————-



476
477
478
479
480
481
482
483
484
485
486
487
488
489
# File 'lib/style_train/color.rb', line 476

def mix(other, ratio=nil)
  ratio = 1-ratio if ratio
  this_ratio = mix_ratio
  ratio ||= this_ratio
  other_ratio = other.mix_ratio
  ratio ||=  other_ratio ? 1-other_ratio : 0.5
  
  color = self.dup
  color.r = self.class.mix(color.r, other.r, ratio)
  color.g = self.class.mix(color.g, other.g, ratio)
  color.b = self.class.mix(color.b, other.b, ratio)
  color.alpha = self.class.mix(color.alpha, other.alpha, ratio)
  color
end

#non_null?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/style_train/color.rb', line 28

def non_null?
  !transparent?
end

#percent(value) ⇒ Object



519
520
521
522
# File 'lib/style_train/color.rb', line 519

def percent(value)
  self.mix_ratio = self.class.normalize_percentage(value)/100.0
  self
end

#render(as = self.class.render_as) ⇒ Object Also known as: to_s



546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'lib/style_train/color.rb', line 546

def render(as=self.class.render_as)
  if as == :hsl
    render_as_hsl
  elsif as == :hsla
    render_as_hsla
  elsif as == :rgb
    render_as_rgb
  elsif as == :rgba
    render_as_rgba
  elsif as == :flat
    render_as_flat
  else
    render_as_hex
  end
end

#render_as_flatObject



564
565
566
567
# File 'lib/style_train/color.rb', line 564

def render_as_flat
  color = flatten
  color.render
end

#render_as_hexObject



569
570
571
572
573
574
575
576
# File 'lib/style_train/color.rb', line 569

def render_as_hex
  if alpha < 1
    render_as_rgba
  else
    set_hex
    "##{hex}"
  end
end

#render_as_hslObject



590
591
592
593
594
595
596
597
# File 'lib/style_train/color.rb', line 590

def render_as_hsl
  if alpha < 1
    render_as_hsla
  else
    set_hsl
    "hsl(#{(h*360).round}, #{s*100}%, #{l*100}%)"
  end
end

#render_as_hslaObject



599
600
601
# File 'lib/style_train/color.rb', line 599

def render_as_hsla
  "hsla(#{(h*360).round}, #{s*100}%, #{l*100}%, #{alpha})"
end

#render_as_rgbObject



578
579
580
581
582
583
584
# File 'lib/style_train/color.rb', line 578

def render_as_rgb
  if alpha < 1
    render_as_rgba
  else
    "rgb(#{r*100}%, #{g*100}%, #{b*100}%)"
  end
end

#render_as_rgbaObject



586
587
588
# File 'lib/style_train/color.rb', line 586

def render_as_rgba
  "rgba(#{r*100}%, #{g*100}%, #{b*100}%, #{alpha})"
end

#reset_for_shiftObject

TRANSFORMATIONS ——————————————–



341
342
343
344
345
# File 'lib/style_train/color.rb', line 341

def reset_for_shift
  self.hex = nil
  self.hex_6 = nil
  set_hsl unless :type == :hsl
end

#rotate(value = 10.degrees) ⇒ Object



404
405
406
407
# File 'lib/style_train/color.rb', line 404

def rotate(value=10.degrees)
  color = self.dup
  color.rotate!(value)
end

#rotate!(value = 10.degrees) ⇒ Object



409
410
411
# File 'lib/style_train/color.rb', line 409

def rotate!(value=10.degrees)
  shift_hue!(value) {|v| self.h = (v + h) % 1 }
end

#rotate_in_temperature!(value) ⇒ Object



435
436
437
438
439
440
441
442
443
# File 'lib/style_train/color.rb', line 435

def rotate_in_temperature!(value)
  set_hsl
  value = self.class.normalize_hue(value)
  unless [COLDEST_HUE, WARMEST_HUE].include?(h)
    new_h = yield(value)
    rotate!((new_h - h)%1)
  end
  self
end

#saturate(value = 0.1) ⇒ Object Also known as: brighten



374
375
376
377
# File 'lib/style_train/color.rb', line 374

def saturate(value=0.1)
  color = self.dup
  color.saturate!(value)
end

#saturate!(value = 0.1) ⇒ Object Also known as: brighten!



379
380
381
# File 'lib/style_train/color.rb', line 379

def saturate!(value=0.1)
  shift!(value) { |v| self.s = [1.0, s + v].min }
end

#set_hexObject



324
325
326
327
328
329
330
331
# File 'lib/style_train/color.rb', line 324

def set_hex
  self.type = :hex
  self.hex = ""
  self.hex << sprintf( "%02X", r*255 );
  self.hex << sprintf( "%02X", g*255 );
  self.hex << sprintf( "%02X", b*255 );
  self.hex_6 = self.class.normalize_hex(hex)
end

#set_hslObject

CONVERSIONS ——————————————————



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/style_train/color.rb', line 277

def set_hsl
  rgb = [r, g, b]
  max = rgb.max 
  min = rgb.min
  avg = ( max + min )/2.0
  diff = ( max - min ).to_f
  lightness = avg
  
  if max == min  # achromatic
    hue = 0
    saturation = 0
  else
    saturation = if avg > 0.6
      lightness / ( 2 - max - min )
    else
      diff / ( max + min )
    end
    
    diff_r = (((max - r) / 6) + (diff / 2)) / diff;
    diff_g = (((max - g) / 6) + (diff / 2)) / diff;
    diff_b = (((max - b) / 6) + (diff / 2)) / diff;
    
    hue = if r == max
      diff_b - diff_g
    elsif g == max
      1/3.0 + diff_r - diff_b
    else
      2/3.0 + diff_g - diff_r
    end
  end
  
  
  hue += 1 if hue < 0
  hue -= 1 if hue > 1

  self.type = :hsl
  self.h = hue
  self.s = saturation
  self.l = lightness
  
  self
end

#set_rgbObject



320
321
322
# File 'lib/style_train/color.rb', line 320

def set_rgb
  self.type = :rgb
end

#shift!(value) {|value| ... } ⇒ Object

Yields:

  • (value)


347
348
349
350
351
352
353
354
# File 'lib/style_train/color.rb', line 347

def shift!(value)
  reset_for_shift
  value = value/100.0 if value.is_a?(Integer)
  value = self.class.normalize_percentage(value)/100.0 if value.is_a?(String)
  value = self.class.normalize_ratio(value) 
  yield(value)
  hsl_to_rgb
end

#shift_hue!(value) {|value| ... } ⇒ Object

Yields:

  • (value)


397
398
399
400
401
402
# File 'lib/style_train/color.rb', line 397

def shift_hue!(value)
  reset_for_shift
  value = self.class.normalize_hue(value)
  yield(value)
  hsl_to_rgb
end

#step(end_color, steps = 10) ⇒ Object



502
503
504
505
506
507
508
509
510
511
512
# File 'lib/style_train/color.rb', line 502

def step(end_color, steps=10)
  start_color = self.dup
  end_color = end_color.dup
  array = [start_color]
  (2..(steps-1)).each do |number|
    ratio = 1 - (steps-number)/steps.to_f
    array << start_color.mix(end_color, ratio)
  end
  array << end_color
  array
end

#transparent?Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/style_train/color.rb', line 24

def transparent?
  type == :transparent
end

#triangulate(offset = 0.0) ⇒ Object



428
429
430
# File 'lib/style_train/color.rb', line 428

def triangulate(offset = 0.0)
  dial(3, offset)
end

#warmer(value = 10.degrees) ⇒ Object



465
466
467
468
# File 'lib/style_train/color.rb', line 465

def warmer(value=10.degrees)
  color = self.dup
  color.warmer!(value)
end

#warmer!(value = 10.degrees) ⇒ Object



445
446
447
448
449
450
451
452
453
# File 'lib/style_train/color.rb', line 445

def warmer!(value=10.degrees)
  rotate_in_temperature!(value) do |v|
    if h < COLDEST_HUE
      [WARMEST_HUE, (h - v)].max.abs
    else
      [1.0-WARMEST_HUE, (h + v)].min.abs
    end
  end
end