style_train 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -294,14 +294,18 @@ CSS
294
294
  end
295
295
  end
296
296
 
297
- def opacity(value)
297
+ def opacity(value, opts={})
298
298
  value = value.to_f
299
299
  str = ""
300
300
  str << property( 'opacity', value )
301
- str << property( 'filter', "alpha(opacity=#{(value*100).to_i})")
301
+ str << alpha( value.to_f*100 ) if opts[:alpha]
302
302
  str
303
303
  end
304
304
 
305
+ def alpha(value)
306
+ property('filter', "alpha(opacity=#{(value.to_i)})")
307
+ end
308
+
305
309
  [
306
310
  'color', 'display', 'float', 'clear', 'visibility', 'cursor',
307
311
  'height', 'width', 'max_height', 'max_width', 'min_height', 'min_width',
@@ -1,5 +1,5 @@
1
1
  class Fixnum
2
- ['px', 'em', 'pt'].each do |meth|
2
+ ['px', 'em', 'pt', 'degrees'].each do |meth|
3
3
  class_eval <<-RUBY
4
4
  def #{meth}
5
5
  self.to_s + "#{meth}"
@@ -13,11 +13,15 @@ class Fixnum
13
13
  end
14
14
 
15
15
  class Float
16
- ['em', 'pt'].each do |meth|
16
+ ['em', 'pt', 'degrees'].each do |meth|
17
17
  class_eval <<-RUBY
18
18
  def #{meth}
19
19
  self.to_s + "#{meth}"
20
20
  end
21
21
  RUBY
22
22
  end
23
+
24
+ def percent
25
+ "#{self}%"
26
+ end
23
27
  end
@@ -0,0 +1,1447 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ Color = StyleTrain::Color unless defined?(Color)
4
+ describe Color do
5
+ TOLERANCE = 0.009
6
+
7
+ describe 'initialization' do
8
+ describe 'auto-detection' do
9
+ it 'raises an error if autodetection fails' do
10
+ lambda{ Color.new('ggg') }.should raise_error(Color::AutodetectionError)
11
+ end
12
+
13
+ describe 'transparent' do
14
+ before :all do
15
+ @trans = Color.new(:transparent)
16
+ @trans_too = Color.new('transparent')
17
+ end
18
+
19
+ it 'has the type transparent' do
20
+ @trans.type.should == @trans_too.type
21
+ @trans.type.should == :transparent
22
+ end
23
+
24
+ it 'has r, g, b values of 0' do
25
+ @trans.r.should == 0
26
+ @trans.g.should == 0
27
+ @trans.b.should == 0
28
+ end
29
+
30
+ it 'has an alpha of 0' do
31
+ @trans.alpha.should == 0
32
+ end
33
+
34
+ it 'should ignore options, alpha, background, etc' do
35
+ color = Color.new(:transparent, :alpha => 1.0, :background => '#666')
36
+ color.type.should == :transparent
37
+ color.alpha.should == 0
38
+ color.background.should be_nil
39
+ end
40
+ end
41
+
42
+ describe 'keyword colors' do
43
+ it 'sets the type appropriately when passed a symbol' do
44
+ Color.new(:lightyellow).type.should == :keyword
45
+ end
46
+
47
+ it 'raises an error if the symbol is not found' do
48
+ lambda{ Color.new(:light_puke) }.should raise_error(
49
+ Color::KeywordError, "Color :light_puke not found as a keyword"
50
+ )
51
+ end
52
+
53
+ it 'should not raise an error if :transparent is given' do
54
+ lambda{ Color.new(:transparent) }.should_not raise_error
55
+ end
56
+
57
+ it 'should set the r, g, and b values based on the key' do
58
+ color = Color.new(:azure)
59
+ color.r.should == 240/255.0
60
+ color.b.should == 1.0
61
+ color.g.should == 1.0
62
+ end
63
+ end
64
+
65
+ describe 'hexidecimal colors' do
66
+ it 'sets the type to :hex' do
67
+ Color.new('#666').type.should == :hex
68
+ Color.new('#666666').type.should == :hex
69
+ end
70
+
71
+ it 'sets the hex_6' do
72
+ Color.new('#444').hex_6.should == 0x444444
73
+ Color.new('#404040').hex_6.should == 0x404040
74
+ end
75
+
76
+ it 'sets the rgb appropriately' do
77
+ @gray = Color.new('#666')
78
+ @red = Color.new('#993300')
79
+ @gold = Color.new('#FC0')
80
+
81
+ @gray.r.should == 102/255.0
82
+ @red.r.should == 153/255.0
83
+ @gold.r.should == 255/255.0
84
+
85
+ @gray.g.should == 102/255.0
86
+ @red.g.should == 51/255.0
87
+ @gold.g.should == 204/255.0
88
+
89
+ @gray.b.should == 102/255.0
90
+ @red.b.should == 0
91
+ @gold.b.should == 0
92
+ end
93
+
94
+ it 'should pass of colors with many arguments' do
95
+ lambda { Color.new('666', 100, 100) }.should raise_error(Color::AutodetectionError)
96
+ end
97
+ end
98
+
99
+ describe 'rgb colors' do
100
+ before do
101
+ @color = Color.new(20,40,60)
102
+ end
103
+
104
+ it 'should set the type to :rgb' do
105
+ @color.type.should == :rgb
106
+ end
107
+
108
+ it 'sets the rgb values appropriately' do
109
+ @color.r.should == 20/255.0
110
+ @color.g.should == 40/255.0
111
+ @color.b.should == 60/255.0
112
+ end
113
+
114
+ it 'takes percentages if a string' do
115
+ color = Color.new(0.percent, 50.percent, 100.percent)
116
+ color.type.should == :rgb
117
+ color.r.should == 0
118
+ color.g.should == 0.5
119
+ color.b.should == 1.0
120
+ end
121
+
122
+ it 'takes a ratio' do
123
+ color = Color.new(0.0, 0.5, 1.0)
124
+ color.type.should == :rgb
125
+ color.r.should == 0
126
+ color.g.should == 0.5
127
+ color.b.should == 1.0
128
+ end
129
+
130
+ it 'raises an error if numbers are too large' do
131
+ lambda{ Color.new(20, 300, 255) }.should raise_error(Color::ByteError)
132
+ end
133
+
134
+ it 'raises an error if the numbers are too small' do
135
+ lambda{ Color.new(20, 100, -155) }.should raise_error(Color::ByteError)
136
+ end
137
+ end
138
+
139
+ describe 'hsl colors' do
140
+ before do
141
+ @color = Color.new( 350, 50.percent, 100.percent )
142
+ end
143
+
144
+ it 'correctly detects the type when first argument is greater than 255' do
145
+ @color.type.should == :hsl
146
+ end
147
+
148
+ it 'takes ratios for s and l' do
149
+ color = Color.new( 120.degrees, 0.0, 0.75 )
150
+ color.type.should == :hsl
151
+ color.h.should == 120.0/360
152
+ color.s.should == 0
153
+ color.l.should == 0.75
154
+ end
155
+
156
+ it 'sets the hsl correctly' do
157
+ color = Color.new(0.degrees, 0.percent, 40.percent)
158
+ color.h.should == 0
159
+ color.s.should == 0
160
+ color.l.should == 0.4
161
+ end
162
+
163
+ it 'converts to rgb correctly' do
164
+ color = Color.new(0.degrees, 0.percent, 40.percent)
165
+ color.r.should == 102/255.0
166
+ color.g.should == 102/255.0
167
+ color.b.should == 102/255.0
168
+
169
+ color = Color.new(210.degrees, 65.percent, 20.percent)
170
+ color.r.should == 0.07
171
+ color.g.should be_within(TOLERANCE).of(0.2)
172
+ color.b.should == 0.33
173
+ end
174
+ end
175
+ end
176
+
177
+ describe 'explicit typing' do
178
+ describe 'keyword' do
179
+ it 'will raise an error if the keyword is not found' do
180
+ lambda { Color.new(:light_puke, :type => :keyword) }.should raise_error(Color::KeywordError)
181
+ end
182
+ end
183
+
184
+ describe 'hexidecimal colors' do
185
+ it 'will convert a string without the preceeding #' do
186
+ color = Color.new('666', :type => :hex )
187
+ color.type.should == :hex
188
+ color.r.should == 102/255.0
189
+ color.g.should == 102/255.0
190
+ color.b.should == 102/255.0
191
+ end
192
+
193
+ it 'raises an error if the string does not match hex color standards' do
194
+ lambda{ Color.new('ggg', :type => :hex) }.should raise_error(ArgumentError)
195
+ end
196
+ end
197
+
198
+ describe 'rgb colors' do
199
+ it 'should work with good numbers' do
200
+ color = Color.new(255,255,0, :type => :rgb)
201
+ color.type.should == :rgb
202
+ color.r.should == 1.0
203
+ color.g.should == 1.0
204
+ color.b.should == 0
205
+ end
206
+
207
+ it 'raises an error if any byte number is out of range' do
208
+ lambda{ Color.new(300, 100, 100, :type => :rgb) }.should raise_error(ArgumentError)
209
+ end
210
+
211
+ it 'raises an error if any percentage is out of range' do
212
+ lambda{ Color.new(300.percent, 100.percent, 100.percent, :type => :rgb) }.should raise_error(ArgumentError)
213
+ end
214
+
215
+ it 'raises an error if any ratio is out of range' do
216
+ lambda{ Color.new(2.0, 1.0, 1.0, :type => :rgb) }.should raise_error(ArgumentError)
217
+ end
218
+ end
219
+
220
+ describe 'hsl colors' do
221
+ it 'will recognize the type even if hue is within byte range' do
222
+ color = Color.new(220, 127, 127, :type => :hsl)
223
+ color.type.should == :hsl
224
+ color.r.should be_within(TOLERANCE).of(0.25)
225
+ color.g.should be_within(TOLERANCE).of(0.416)
226
+ color.b.should be_within(TOLERANCE).of(0.75)
227
+ end
228
+
229
+ it 'accepts ratios for hue' do
230
+ color = Color.new(0.611111, 0.5, 0.5, :type => :hsl)
231
+ color.type.should == :hsl
232
+ color.r.should == 0.25
233
+ color.g.should be_within(TOLERANCE).of(0.416)
234
+ color.b.should == 0.75
235
+ end
236
+
237
+ it 'accepts percentages for hue' do
238
+ color = Color.new(61.1111.percent, 50.percent, 50.percent, :type => :hsl)
239
+ color.type.should == :hsl
240
+ color.r.should == 0.25
241
+ color.g.should be_within(TOLERANCE).of(0.416)
242
+ color.b.should == 0.75
243
+ end
244
+ end
245
+ end
246
+
247
+ describe 'alpha' do
248
+ describe 'autodetection' do
249
+ it 'ignores the alpha with a transparent color' do
250
+ Color.new(:transparent, :alpha => 0.5).alpha.should == 0.0
251
+ end
252
+
253
+ it 'sets the alpha with a keyword type' do
254
+ Color.new(:lightyellow, :alpha => 0.5).alpha.should == 0.5
255
+ end
256
+
257
+ it 'sets the alpha with a hex color' do
258
+ Color.new('#666', :alpha => 0.75).alpha.should == 0.75
259
+ end
260
+
261
+ it 'sets the alpha with a rgb color' do
262
+ Color.new(100.percent, 50.percent, 25.percent, :alpha => 0.25).alpha.should == 0.25
263
+ end
264
+
265
+ it 'sets the alpha with a hsl color' do
266
+ Color.new(20.degrees, 50.percent, 50.percent, :alpha => 0.10).alpha.should == 0.1
267
+ end
268
+
269
+ it 'sets the alpha to 1.0 by default' do
270
+ Color.new(:lightyellow).alpha.should == 1.0
271
+ end
272
+ end
273
+
274
+ describe 'explicit typing' do
275
+ it 'ignores the alpha with a transparent color' do
276
+ Color.new(:transparent, :alpha => 0.5, :type => :transparent).alpha.should == 0.0
277
+ end
278
+
279
+ it 'sets the alpha with a keyword type' do
280
+ Color.new(:lightyellow, :type => :keyword, :alpha => 0.5).alpha.should == 0.5
281
+ end
282
+
283
+ it 'sets the alpha with a hex color' do
284
+ Color.new('#123456', :type => :hex, :alpha => 0.25).alpha.should == 0.25
285
+ end
286
+
287
+ it 'sets the alpha with a rgb color' do
288
+ Color.new(255,127,64, :type => :rgb, :alpha => 0.1).alpha.should == 0.1
289
+ end
290
+
291
+ it 'sets the alpha with a hsl color' do
292
+ Color.new(20, 50.percent, 50.percent, :type => :hsl, :alpha => 0.75).alpha.should == 0.75
293
+ end
294
+ end
295
+ end
296
+
297
+ describe 'background' do
298
+ describe 'autodetection' do
299
+ describe 'different detection types' do
300
+ it 'ignores the background with a transparent color' do
301
+ Color.new(:transparent, :background => :black).background.should == nil
302
+ end
303
+
304
+ it 'sets the background with a keyword type' do
305
+ Color.new(:lightyellow, :background => :black).background.should == Color.new(:black)
306
+ end
307
+
308
+ it 'sets the background with a hex color' do
309
+ Color.new('#666', :background => :black).background.should == Color.new(:black)
310
+ end
311
+
312
+ it 'sets the background with a rgb color' do
313
+ Color.new(100.percent, 50.percent, 25.percent, :background => :black).background.should == Color.new(:black)
314
+ end
315
+
316
+ it 'sets the background with a hsl color' do
317
+ Color.new(20.degrees, 50.percent, 50.percent, :background => :black).background.should == Color.new(:black)
318
+ end
319
+
320
+ it 'sets the background to :white by default' do
321
+ Color.new(:lightyellow).background.should == Color.new(:white)
322
+ end
323
+ end
324
+
325
+ describe "different background types/arguments" do
326
+ it 'takes background a keyword arguments' do
327
+ Color.new(:lightyellow, :background => :black).background.should == Color.new(:black)
328
+ end
329
+
330
+ it 'takes background with hex color arguments' do
331
+ Color.new(:lightyellow, :background => '#000').background.should == Color.new(:black)
332
+ end
333
+
334
+ it 'takes background with rgb color arguments' do
335
+ Color.new(:lightyellow, :background => [0,0,0]).background.should == Color.new(:black)
336
+ end
337
+
338
+ it 'takes background with hsl color arguments' do
339
+ Color.new(:lightyellow, :background => [0.degrees, 0, 0]).background.should == Color.new(:black)
340
+ end
341
+ end
342
+ end
343
+
344
+ describe 'explicit typing' do
345
+ it 'ignores the background with a transparent color' do
346
+ Color.new(:transparent, :background => :black, :type => :transparent).background.should == nil
347
+ end
348
+
349
+ it 'sets the background with a keyword type' do
350
+ Color.new(:lightyellow, :background => :black, :type => :keyword).background.should == Color.new(:black)
351
+ end
352
+
353
+ it 'sets the background with a hex color' do
354
+ Color.new('#666', :background => :black, :type => :hex).background.should == Color.new(:black)
355
+ end
356
+
357
+ it 'sets the background with a rgb color' do
358
+ Color.new(100.percent, 50.percent, 25.percent, :background => :black, :type => :rgb).background.should == Color.new(:black)
359
+ end
360
+
361
+ it 'sets the background with a hsl color' do
362
+ Color.new(20.degrees, 50.percent, 50.percent, :background => :black, :type => :hsl).background.should == Color.new(:black)
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ describe 'alpha' do
369
+ describe 'acceptable values' do
370
+ before do
371
+ @color = Color.new('666')
372
+ end
373
+
374
+ it 'takes ratios' do
375
+ @color.alpha = 0.5
376
+ @color.alpha.should == 0.5
377
+ end
378
+
379
+ it 'should raise an error if the ratio is out of range' do
380
+ lambda { @color.alpha = 1.1 }.should raise_error( Color::RatioError )
381
+ end
382
+
383
+ it 'takes percentages' do
384
+ @color.alpha = 72.5.percent
385
+ @color.alpha.should == 0.725
386
+ end
387
+
388
+ it 'accepts integers as percentages' do
389
+ @color.alpha = 78
390
+ @color.alpha.should == 0.78
391
+ end
392
+
393
+ it 'should raise an error if the percentage is out of range' do
394
+ lambda { @color.alpha = 300.percent }.should raise_error(Color::PercentageError)
395
+ end
396
+ end
397
+ end
398
+
399
+ describe 'background' do
400
+ before do
401
+ @background = Color.new(:lightyellow)
402
+ @color = Color.new(:black, :alpha => 0.5)
403
+ end
404
+
405
+ it 'takes a color object' do
406
+ @color.background = @background
407
+ @color.background.should == @background
408
+ end
409
+
410
+ it 'otherwise tries to construct a color object from the arguments' do
411
+ @color.background = :lightyellow
412
+ @color.background.should == @background
413
+ end
414
+ end
415
+
416
+ describe 'comparisons' do
417
+ it 'should be === if the colors have the same object id' do
418
+ (Color.new(:lightyellow) === Color.new(:lightyellow)).should == false
419
+ color = Color.new(:lightyellow)
420
+ (color === color).should == true
421
+ end
422
+
423
+ it 'should be =~ if the colors have the same rgb, but different alphas' do
424
+ (Color.new(:lightyellow, :alpha => 0.5) =~ Color.new(:lightyellow)).should == true
425
+ end
426
+
427
+ describe '==' do
428
+ it 'should be false if the alpha is different' do
429
+ Color.new(255, 255, 224, :alpha => 0.5).should_not == Color.new(:lightyellow)
430
+ end
431
+
432
+ it 'should be false if the rgb values are different' do
433
+ Color.new(255, 255, 225, :alpha => 1.0).should_not == Color.new(:lightyellow)
434
+ end
435
+
436
+ it 'should be == if the colors have the same rgb and alpha' do
437
+ Color.new(255, 255, 224, :alpha => 1.0).should == Color.new(:lightyellow)
438
+ end
439
+
440
+ it 'should be indifferent to backgrounds' do
441
+ Color.new(255, 255, 224, :alpha => 1.0, :background => :black).should == Color.new(:lightyellow)
442
+ end
443
+ end
444
+ end
445
+
446
+ describe 'normalizer' do
447
+ describe 'percentages' do
448
+ it 'should return valid integers' do
449
+ Color.normalize_percentage(25.percent).should == 25
450
+ end
451
+
452
+ it 'should return valid floats' do
453
+ Color.normalize_percentage(50.5.percent).should == 50.5
454
+ end
455
+
456
+ it 'works with an integer' do
457
+ Color.normalize_percentage(50).should == 50
458
+ end
459
+
460
+ it 'works with floats' do
461
+ Color.normalize_percentage(20.5).should == 20.5
462
+ end
463
+
464
+ it 'raises an error if greater than 100' do
465
+ lambda{ Color.normalize_percentage(105) }.should raise_error(Color::PercentageError)
466
+ end
467
+
468
+ it 'raises an error if lower than 0' do
469
+ lambda{ Color.normalize_percentage(-25) }.should raise_error(Color::PercentageError)
470
+ end
471
+
472
+ it 'converts to byte' do
473
+ Color.percentage_to_byte(100.0).should == 255
474
+ Color.percentage_to_byte(0).should == 0
475
+ Color.percentage_to_byte(50.percent).should == 127
476
+ end
477
+ end
478
+
479
+ describe 'degrees' do
480
+ it 'should return a number between 0 and 359 when given such a number' do
481
+ Color.normalize_degrees(30).should == 30/360.0
482
+ Color.normalize_degrees(42).should == 42/360.0
483
+ end
484
+
485
+ it 'should return a number when given a degree string' do
486
+ Color.normalize_degrees(42.degrees).should == 42/360.0
487
+ end
488
+
489
+ it 'should return nil when given a string without degrees' do
490
+ Color.normalize_degrees('42').should == nil
491
+ end
492
+
493
+ it 'should normalize a number greater than 359' do
494
+ Color.normalize_degrees(360).should == 0
495
+ Color.normalize_degrees(460).should == 100/360.0
496
+ end
497
+
498
+ it 'should normalize negative number' do
499
+ Color.normalize_degrees(-127).should == 233/360.0
500
+ end
501
+
502
+ it 'works with strings containing "degrees"' do
503
+ Color.normalize_degrees(127.degrees).should == 127/360.0
504
+ end
505
+
506
+ it 'rejects percentage strings' do
507
+ Color.normalize_degrees(12.percent).should == nil
508
+ end
509
+ end
510
+
511
+ describe 'ratios' do
512
+ it 'raises an error if below 0' do
513
+ lambda{ Color.ratio_to_byte(-0.1) }.should raise_error(Color::RatioError)
514
+ end
515
+
516
+ it 'raises an error if it is above 1.0' do
517
+ lambda{ Color.ratio_to_byte(1.1)}.should raise_error(Color::RatioError)
518
+ end
519
+
520
+ it 'converts correctly to byte otherwise' do
521
+ Color.ratio_to_byte(0.5).should == 127
522
+ end
523
+ end
524
+ end
525
+
526
+ describe 'type transformation' do
527
+ before do
528
+ @red_values = {
529
+ :rgb => [100, 25, 25],
530
+ :hex => ['641919', 0x641919],
531
+ :hsl => [0.degrees, 0.6, 0.25]
532
+ }
533
+ @green_values = {
534
+ :rgb => [25, 100, 25],
535
+ :hex => ['196419', 0x196419],
536
+ :hsl => [120.degrees, 0.60, 0.25]
537
+ }
538
+ @blue_values = {
539
+ :rgb => [25, 25, 100],
540
+ :hex => ['191964', 0x191964],
541
+ :hsl => [240.degrees, 0.60, 0.25]
542
+ }
543
+ end
544
+
545
+ describe '#set_hsl' do
546
+ before do
547
+ @red = Color.new(*@red_values[:rgb])
548
+ @red.set_hsl
549
+ @blue = Color.new(*@blue_values[:rgb])
550
+ @blue.set_hsl
551
+ @green = Color.new(*@green_values[:rgb])
552
+ @green.set_hsl
553
+ end
554
+
555
+ it 'changes the type to :hsl' do
556
+ @red.type.should == :hsl
557
+ @blue.type.should == :hsl
558
+ @green.type.should == :hsl
559
+ end
560
+
561
+ it 'converts adds hsl value' do
562
+ @red.h.should be_within(TOLERANCE).of(Color.normalize_degrees(@red_values[:hsl][0]))
563
+ @red.s.should be_within(TOLERANCE).of( @red_values[:hsl][1])
564
+ @red.l.should be_within(TOLERANCE).of(@red_values[:hsl][2])
565
+
566
+ @green.h.should be_within(TOLERANCE).of(Color.normalize_degrees(@green_values[:hsl][0]))
567
+ @green.s.should be_within(TOLERANCE).of( @green_values[:hsl][1])
568
+ @green.l.should be_within(TOLERANCE).of(@green_values[:hsl][2])
569
+
570
+ @blue.h.should be_within(TOLERANCE).of(Color.normalize_degrees(@blue_values[:hsl][0]))
571
+ @blue.s.should be_within(TOLERANCE).of( @blue_values[:hsl][1])
572
+ @blue.l.should be_within(TOLERANCE).of(@blue_values[:hsl][2])
573
+ end
574
+ end
575
+
576
+ describe '#set_rgb' do
577
+ before do
578
+ @color = Color.new('#555')
579
+ @color.set_rgb
580
+ end
581
+
582
+ it 'changes the type' do
583
+ @color.type.should == :rgb
584
+ end
585
+ end
586
+
587
+ describe '#set_hex' do
588
+ before do
589
+ @red = Color.new(*@red_values[:rgb])
590
+ end
591
+
592
+ it 'sets the hex and hex_6' do
593
+ @red.hex = 'foo'
594
+ @red.hex_6 = 'foo'
595
+ @red.set_hex
596
+ @red.hex.should == @red_values[:hex][0]
597
+ @red.hex_6.should == @red_values[:hex][1]
598
+ end
599
+
600
+ it 'sets the type to :hex' do
601
+ @red.set_hex
602
+ @red.type.should == :hex
603
+ end
604
+ end
605
+
606
+ describe '#hsl_to_rgb' do
607
+ before do
608
+ @red = Color.new(*@red_values[:hsl])
609
+ @red.set_hex
610
+ @red.l += 0.1
611
+ @red.hsl_to_rgb
612
+ end
613
+
614
+ it 'resets the r, g, b values from h, s, l' do
615
+ @red.r.should be_within(TOLERANCE).of(143/255.0)
616
+ @red.g.should be_within(TOLERANCE).of(36/255.0)
617
+ @red.b.should be_within(TOLERANCE).of(36/255.0)
618
+ end
619
+
620
+ it 'clears the hex' do
621
+ @red.hex.should == nil
622
+ @red.hex_6.should == nil
623
+ end
624
+ end
625
+ end
626
+
627
+ describe 'modification' do
628
+ before do
629
+ @red_values = {
630
+ :rgb => [100, 25, 25],
631
+ :hex => ['641919', 0x641919],
632
+ :hsl => [Color.normalize_degrees(0.degrees), 0.6, 0.25]
633
+ }
634
+ @red = Color.new(*@red_values[:rgb])
635
+ end
636
+
637
+ describe 'shift' do
638
+ describe 'lighten!' do
639
+ before do
640
+ @red.lighten!
641
+ end
642
+
643
+ it 'adds 10% to the l value by default' do
644
+ @red.l.should be_within(TOLERANCE).of(@red_values[:hsl][2] + 0.1)
645
+ end
646
+
647
+ it 'recalculates the rgb' do
648
+ @red.r.should be_within(TOLERANCE).of(143/255.0)
649
+ @red.g.should be_within(TOLERANCE).of(36/255.0)
650
+ @red.b.should be_within(TOLERANCE).of(36/255.0)
651
+ end
652
+
653
+ it 'takes a percentage argument and adds that from the l' do
654
+ l = @red.l
655
+ @red.lighten!(30.percent)
656
+ @red.l.should == l + 0.30
657
+ end
658
+
659
+ it 'takes a ratio argument' do
660
+ l = @red.l
661
+ @red.lighten!(0.21)
662
+ @red.l.should == l + 0.21
663
+ end
664
+
665
+ it 'assumes integers are percentages' do
666
+ l = @red.l
667
+ @red.lighten!(20)
668
+ @red.l.should == l + 0.2
669
+ @red.lighten!(80)
670
+ @red.l.should == 1.0
671
+ end
672
+
673
+ it 'should cap at 100 percent' do
674
+ @red.lighten!(0.80)
675
+ @red.l.should == 1.0
676
+ end
677
+ end
678
+
679
+ describe 'lighten' do
680
+ before do
681
+ @less_red = @red.lighten
682
+ end
683
+
684
+ it 'should not affect the originating color' do
685
+ @red.type.should == :rgb
686
+ @red.r.should be_within(TOLERANCE).of(0.4)
687
+ end
688
+
689
+ it 'should return a transformed object' do
690
+ @less_red.r.should be_within(TOLERANCE).of(143/255.0)
691
+ @less_red.g.should be_within(TOLERANCE).of(36/255.0)
692
+ @less_red.b.should be_within(TOLERANCE).of(36/255.0)
693
+ end
694
+ end
695
+
696
+ describe 'darken!' do
697
+ before do
698
+ @red.darken!
699
+ end
700
+
701
+ it 'makes subtracts 10% to the l value by default' do
702
+ @red.l.should be_within(TOLERANCE).of(@red_values[:hsl][2] - 0.1)
703
+ end
704
+
705
+ it 'recalculates the rgb' do
706
+ @red.r.should be_within(TOLERANCE).of(61/255.0)
707
+ @red.g.should be_within(TOLERANCE).of(15/255.0)
708
+ @red.b.should be_within(TOLERANCE).of(15/255.0)
709
+ end
710
+
711
+ it 'takes a percentage argument and subtracts that from the l' do
712
+ l = @red.l
713
+ @red.darken!(5.percent)
714
+ @red.l.should == l - 0.05
715
+ end
716
+
717
+ it 'takes a ratio argument' do
718
+ l = @red.l
719
+ @red.darken!(0.07)
720
+ @red.l.should == l - 0.07
721
+ end
722
+ end
723
+
724
+ describe 'darken' do
725
+ before do
726
+ @darker_red = @red.darken
727
+ end
728
+
729
+ it 'should not affect the originating color' do
730
+ @red.type.should == :rgb
731
+ @red.r.should be_within(TOLERANCE).of(0.4)
732
+ end
733
+
734
+ it 'should return a transformed object' do
735
+ @darker_red.r.should be_within(TOLERANCE).of(61/255.0)
736
+ @darker_red.g.should be_within(TOLERANCE).of(15/255.0)
737
+ @darker_red.b.should be_within(TOLERANCE).of(15/255.0)
738
+ end
739
+ end
740
+
741
+ describe 'saturate!' do
742
+ before do
743
+ @red.saturate!
744
+ end
745
+
746
+ it 'adds 10% to the s value by default' do
747
+ @red.s.should be_within(TOLERANCE).of(@red_values[:hsl][1] + 0.1)
748
+ end
749
+
750
+ it 'recalculates the rgb' do
751
+ @red.r.should be_within(TOLERANCE).of(108/255.0)
752
+ @red.g.should be_within(TOLERANCE).of(19/255.0)
753
+ @red.b.should be_within(TOLERANCE).of(19/255.0)
754
+ end
755
+
756
+ it 'takes a percentage argument and adds that from the s' do
757
+ s = @red.s
758
+ @red.saturate!(30.percent)
759
+ @red.s.should == s + 0.30
760
+ end
761
+
762
+ it 'takes a ratio argument' do
763
+ s = @red.s
764
+ @red.saturate!(0.21)
765
+ @red.s.should be_within(TOLERANCE).of(s + 0.21)
766
+ end
767
+
768
+ it 'assumes integers are percentages' do
769
+ s = @red.s
770
+ @red.saturate!(20)
771
+ @red.s.should == s + 0.2
772
+ @red.saturate!(80)
773
+ @red.s.should == 1.0
774
+ end
775
+
776
+ it 'should cap at 100 percent' do
777
+ @red.saturate!(0.80)
778
+ @red.s.should == 1.0
779
+ end
780
+
781
+ it 'aliases to #brighten' do
782
+ @red.brighten!(0.8)
783
+ @red.s.should == 1.0
784
+ end
785
+ end
786
+
787
+ describe 'saturate' do
788
+ before do
789
+ @brighter_red = @red.saturate
790
+ end
791
+
792
+ it 'should not affect the originating color' do
793
+ @red.type.should == :rgb
794
+ @red.r.should be_within(TOLERANCE).of(0.4)
795
+ end
796
+
797
+ it 'should return a transformed object' do
798
+ @brighter_red.r.should be_within(TOLERANCE).of(108/255.0)
799
+ @brighter_red.g.should be_within(TOLERANCE).of(19/255.0)
800
+ @brighter_red.b.should be_within(TOLERANCE).of(19/255.0)
801
+ end
802
+ end
803
+
804
+ describe 'dull!' do
805
+ before do
806
+ @red.dull!
807
+ end
808
+
809
+ it 'adds 10% to the s value by default' do
810
+ @red.s.should be_within(TOLERANCE).of(@red_values[:hsl][1] - 0.1)
811
+ end
812
+
813
+ it 'recalculates the rgb' do
814
+ @red.r.should be_within(TOLERANCE).of(96/255.0)
815
+ @red.g.should be_within(TOLERANCE).of(32/255.0)
816
+ @red.b.should be_within(TOLERANCE).of(32/255.0)
817
+ end
818
+
819
+ it 'takes a percentage argument and adds that from the s' do
820
+ s = @red.s
821
+ @red.dull!(30.percent)
822
+ @red.s.should be_within(TOLERANCE).of(s - 0.30)
823
+ end
824
+
825
+ it 'takes a ratio argument' do
826
+ s = @red.s
827
+ @red.dull!(0.21)
828
+ @red.s.should be_within(TOLERANCE).of(s - 0.21)
829
+ end
830
+
831
+ it 'assumes integers are percentages' do
832
+ s = @red.s
833
+ @red.dull!(20)
834
+ @red.s.should be_within(TOLERANCE).of(s - 0.2)
835
+ @red.dull!(80)
836
+ @red.s.should == 0.0
837
+ end
838
+
839
+ it 'should cap at 100 percent' do
840
+ @red.dull!(0.80)
841
+ @red.s.should == 0.0
842
+ end
843
+
844
+ it 'aliases to #desaturate' do
845
+ @red.desaturate!(0.8)
846
+ @red.s.should == 0.0
847
+ end
848
+ end
849
+
850
+ describe 'dull' do
851
+ before do
852
+ @dull_red = @red.dull
853
+ end
854
+
855
+ it 'should not affect the originating color' do
856
+ @red.type.should == :rgb
857
+ @red.r.should be_within(TOLERANCE).of(0.4)
858
+ end
859
+
860
+ it 'should return a transformed object' do
861
+ @dull_red.r.should be_within(TOLERANCE).of(96/255.0)
862
+ @dull_red.g.should be_within(TOLERANCE).of(32/255.0)
863
+ @dull_red.b.should be_within(TOLERANCE).of(32/255.0)
864
+ end
865
+ end
866
+ end
867
+
868
+ describe 'rotate' do
869
+ describe 'arbitrary' do
870
+ it 'defaults to 10 degrees' do
871
+ @new = @red.rotate
872
+ @new.h.should be_within(TOLERANCE).of(10/360.0)
873
+ end
874
+
875
+ it 'takes other positive degree values' do
876
+ @new = @red.rotate(30.degrees)
877
+ @new.h.should be_within(TOLERANCE).of(30/360.0 )
878
+ end
879
+
880
+ it 'takes negative degrees' do
881
+ @new = @red.rotate(-20.degrees)
882
+ @new.h.should be_within(TOLERANCE).of((360-20)/360.0 )
883
+ end
884
+
885
+ it 'will rotate beyond end points' do
886
+ @new = @red.rotate(300.degrees)
887
+ @new.h.should be_within(TOLERANCE).of(300/360.0)
888
+
889
+ @new.rotate!(100.degrees)
890
+ @new.h.should be_within(TOLERANCE).of(40/360.0)
891
+ end
892
+
893
+ it 'takes ratios' do
894
+ @red.rotate(0.5).h.should be_within(TOLERANCE).of(0.5)
895
+ end
896
+
897
+ it 'calculates the rgb values' do
898
+ @new = @red.rotate(0.5)
899
+ @new.r.should be_within(TOLERANCE).of(26/255.0)
900
+ @new.g.should be_within(TOLERANCE).of(102/255.0)
901
+ @new.b.should be_within(TOLERANCE).of(102/255.0)
902
+ end
903
+
904
+ it 'returns a new color object' do
905
+ @new = @red.rotate(0.5)
906
+ @new.should_not == @red
907
+ end
908
+
909
+ it 'does not modify the existing object' do
910
+ @red.rotate(0.5)
911
+ @red.type.should == :rgb
912
+ @red.r.should be_within(TOLERANCE).of(@red_values[:rgb][0]/255.0)
913
+ end
914
+
915
+ it 'has a ! method that modifies self' do
916
+ @red.rotate!(0.5)
917
+ @red.type.should == :hsl
918
+ @red.r.should be_within(TOLERANCE).of(26/255.0)
919
+ end
920
+ end
921
+
922
+ describe 'compliment' do
923
+ it 'rotates half way around' do
924
+ @red.compliment.should == @red.rotate(0.5)
925
+ end
926
+ end
927
+
928
+ describe '#dial' do
929
+ it 'gives triangular colors' do
930
+ @red.triangulate.should == [@red, @red.rotate(120.degrees), @red.rotate(240.degrees)]
931
+ end
932
+
933
+ it 'gives offset triangular colors' do
934
+ dial = @red.triangulate(1/6.0)
935
+ dial[0].should == @red.rotate(1/6.0)
936
+ dial[1].should == @red.rotate(0.5)
937
+ dial[2].should == @red.rotate(5/6.0)
938
+ end
939
+
940
+ it 'dialing allows dividing by any integer' do
941
+ @red.dial(5).should == [
942
+ @red,
943
+ @red.rotate((360/5.0).degrees),
944
+ @red.rotate((2*360/5.0).degrees),
945
+ @red.rotate((3*360/5.0).degrees),
946
+ @red.rotate((4*360/5.0).degrees)
947
+ ]
948
+ end
949
+
950
+ it 'dailing allows offset too' do
951
+ @red.dial(5, 120.degrees).should == [
952
+ @red.rotate(120.degrees),
953
+ @red.rotate((120 + 360/5.0).degrees),
954
+ @red.rotate((120 + 2*360/5.0).degrees),
955
+ @red.rotate((120 + 3*360/5.0).degrees),
956
+ @red.rotate((120 + 4*360/5.0).degrees)
957
+ ]
958
+ end
959
+ end
960
+
961
+ describe 'warmer' do
962
+ it 'does nothing if at the warmest hue' do
963
+ @red.rotate!(Color::WARMEST_HUE)
964
+ @red.warmer.should == @red
965
+ end
966
+
967
+ it 'does nothing if at the coldest hue' do
968
+ @red.rotate!(Color::COLDEST_HUE)
969
+ @red.warmer.should == @red
970
+ end
971
+
972
+ describe 'direction' do
973
+ before do
974
+ @red.rotate!(0.5)
975
+ end
976
+
977
+ describe 'hue is between 0 degrees and 240 degrees' do
978
+ it 'defaults to rotating 10 degrees lower' do
979
+ @red.warmer.h.should be_within(TOLERANCE).of( 0.5 - 10/360.0 )
980
+ end
981
+
982
+ it 'will not go below the warmest point' do
983
+ # currently at 180
984
+ @red.rotate!(-175.degrees) # to 5 degrees
985
+ @red.warmer.h.should be_within(TOLERANCE).of(0.0) # subtract 10 degrees, should stop at 0
986
+ end
987
+
988
+ it 'takes an custom rotation amount' do
989
+ @red.warmer(0.4).h.should be_within(TOLERANCE).of(0.5 - 0.4)
990
+ end
991
+ end
992
+
993
+ describe "hue is between 240 degrees and 360" do
994
+ before do
995
+ @red.rotate! 0.25 # 270 degrees
996
+ end
997
+
998
+ it 'defaults to rotating 10 degrees higher' do
999
+ @red.warmer.h.should be_within( TOLERANCE ).of( 0.75 + 10/360.0 )
1000
+ end
1001
+
1002
+ it 'takes a custom rotation amount' do
1003
+ @red.warmer(0.2).h.should be_within( TOLERANCE ).of( 0.95 )
1004
+ end
1005
+
1006
+ it 'will not go higher than 360' do
1007
+ @red.warmer(0.3).h.should be_within( TOLERANCE ).of( 0.0 )
1008
+ end
1009
+ end
1010
+ end
1011
+ end
1012
+
1013
+ describe 'cooler' do
1014
+ it 'does nothing if at the warmest hue' do
1015
+ @red.rotate!(Color::WARMEST_HUE)
1016
+ @red.cooler.should == @red
1017
+ end
1018
+
1019
+ it 'does nothing if at the coldest hue' do
1020
+ @red.rotate!(Color::COLDEST_HUE)
1021
+ @red.cooler.should == @red
1022
+ end
1023
+
1024
+ describe 'direction' do
1025
+ before do
1026
+ @red.rotate!(0.5)
1027
+ end
1028
+
1029
+ describe 'hue is between 0 degrees and 240 degrees' do
1030
+ it 'defaults to rotating 10 degrees higher' do
1031
+ @red.cooler.h.should be_within(TOLERANCE).of( 0.5 + 10/360.0 )
1032
+ end
1033
+
1034
+ it 'will not go below the coolest point' do
1035
+ # currently at 180
1036
+ @red.rotate!(60.degrees) # change to 235 degrees
1037
+ @red.cooler.h.should be_within(TOLERANCE).of(Color::COLDEST_HUE) # adding 10 degrees should stop at 240
1038
+ end
1039
+
1040
+ it 'takes an custom rotation amount' do
1041
+ @red.cooler(0.1).h.should be_within(TOLERANCE).of(0.5 + 0.1)
1042
+ end
1043
+ end
1044
+
1045
+ describe "hue is between 240 degrees and 360" do
1046
+ before do
1047
+ @red.rotate! 0.25 # 270 degrees = 0.75
1048
+ end
1049
+
1050
+ it 'defaults to rotating 10 degrees lower' do
1051
+ @red.cooler.h.should be_within( TOLERANCE ).of( 0.75 - 10/360.0 )
1052
+ end
1053
+
1054
+ it 'takes a custom rotation amount' do
1055
+ @red.cooler(0.05).h.should be_within( TOLERANCE ).of( 0.70 )
1056
+ end
1057
+
1058
+ it 'will not go lower than than 240 degress' do
1059
+ @red.cooler(0.1).h.should be_within( TOLERANCE ).of( Color::COLDEST_HUE )
1060
+ end
1061
+ end
1062
+ end
1063
+ end
1064
+ end
1065
+
1066
+ describe 'combining colors' do
1067
+ before :all do
1068
+ @black = Color.new('#000')
1069
+ @yellow = Color.new(:lightyellow)
1070
+ @trans = Color.new(:lightyellow, :alpha => 0.5)
1071
+ end
1072
+
1073
+ describe 'layering' do
1074
+ before do
1075
+ @white = Color.new('#FFF')
1076
+ @shadow = Color.new('#000', :alpha => 0.5)
1077
+ @dark_blue = Color.new(20,40,60, :alpha => 0.5)
1078
+ end
1079
+
1080
+ describe 'r, g, b values' do
1081
+ describe 'opaque top layer' do
1082
+ it 'should have the r, g, b values of the top layer' do
1083
+ color = @shadow.layer(@white)
1084
+ color.r.should == 1.0
1085
+ color.g.should == 1.0
1086
+ color.b.should == 1.0
1087
+ end
1088
+ end
1089
+
1090
+ describe 'opaque bottom layer' do
1091
+ before do
1092
+ @color = @white.layer(@shadow)
1093
+ end
1094
+
1095
+ it 'should mix the r, g, and b in proportion to the top layer\'s alpha' do
1096
+ @color.r.should == 0.5
1097
+ @color.g.should == 0.5
1098
+ @color.b.should == 0.5
1099
+ @color.alpha.should == 1.0
1100
+
1101
+ red = Color.new(153,0,0, :alpha => 0.25)
1102
+ color = @white.layer(red)
1103
+ color.r.should == 0.6*0.25 + 1.0*0.75
1104
+ color.g.should == 0*0.25 + 1.0*0.75
1105
+ color.b.should == 0*0.25 + 1.0*0.75
1106
+ end
1107
+ end
1108
+ end
1109
+
1110
+ describe 'alpha blending' do
1111
+ it 'should be 1.0 if bottom layer is opaque' do
1112
+ color = @white.layer(@shadow)
1113
+ color.alpha.should == 1.0
1114
+ end
1115
+
1116
+ it 'should be 1.0 if the top layer is opaque' do
1117
+ color = @shadow.layer(@white)
1118
+ color.alpha.should == 1.0
1119
+ end
1120
+
1121
+ it 'should have an alpha greater than or equal to the composites' do
1122
+ color = @dark_blue.layer(@shadow)
1123
+ (color.alpha >= @dark_blue.alpha).should be_true
1124
+ (color.alpha >= @shadow.alpha).should be_true
1125
+ end
1126
+
1127
+ it 'should calculate the blending of two alphas properly' do
1128
+ color = @dark_blue.layer(@shadow)
1129
+ color.alpha.should == 0.75 # 0.5 for the base color, plus 0.5 of the remaining transparency
1130
+ end
1131
+ end
1132
+ end
1133
+
1134
+ describe 'mix' do
1135
+ it 'should not affect either color' do
1136
+ black = @black.dup
1137
+ yellow = @yellow.dup
1138
+ @black.mix(@yellow)
1139
+ @black.should == black
1140
+ @yellow.should == yellow
1141
+ end
1142
+
1143
+ it 'mixes half of each by default' do
1144
+ color = @black.mix(@yellow)
1145
+ color.r.should == (@yellow.r/2.0)
1146
+ color.g.should == (@yellow.g/2.0)
1147
+ color.b.should == (@yellow.b/2.0)
1148
+ color.alpha.should == 1.0
1149
+ end
1150
+
1151
+ it 'mixes alphas' do
1152
+ color = @black.mix(@trans)
1153
+ color.r.should == (@yellow.r/2.0)
1154
+ color.g.should == (@yellow.g/2.0)
1155
+ color.b.should == (@yellow.b/2.0)
1156
+ color.alpha.should == 0.75
1157
+ end
1158
+
1159
+ it 'returns a copy, and does not alter the original' do
1160
+ color = @black.mix(@trans)
1161
+ color.should_not === @black
1162
+ color.should_not === @trans
1163
+ end
1164
+
1165
+ describe 'on another ratio' do
1166
+ it 'will mix on a ratio' do
1167
+ color = @black.mix(@trans, 0.25)
1168
+ color.r.should == @trans.r*0.25
1169
+ color.b.should == @trans.b*0.25
1170
+ color.g.should == @trans.g*0.25
1171
+ color.alpha.should == 1.0*0.75 + 0.5*0.25
1172
+ end
1173
+
1174
+ describe '#percent alternate syntax' do
1175
+ it 'sets the mix ratio on the color being mixed in' do
1176
+ @trans.percent(13)
1177
+ @trans.mix_ratio.should == 0.13
1178
+ end
1179
+
1180
+ it 'will be used by the mix when applied to the first color' do
1181
+ color = @black.percent(75).mix(@trans)
1182
+ color.r.should == @trans.r*0.25
1183
+ color.b.should == @trans.b*0.25
1184
+ color.g.should == @trans.g*0.25
1185
+ color.alpha.should == 1.0*0.75 + 0.5*0.25
1186
+ end
1187
+
1188
+ it 'will be used by the mix when applied to the second color' do
1189
+ color = @black.mix(@trans.percent(25))
1190
+ color.r.should == @trans.r*0.25
1191
+ color.b.should == @trans.b*0.25
1192
+ color.g.should == @trans.g*0.25
1193
+ color.alpha.should == 1.0*0.75 + 0.5*0.25
1194
+ end
1195
+
1196
+ it 'consumes the mix ratio' do
1197
+ color = @black.percent(75).mix(@trans.percent(75))
1198
+ @black.mix_ratio.should be_nil
1199
+ @trans.mix_ratio.should be_nil
1200
+ end
1201
+ end
1202
+ end
1203
+ end
1204
+
1205
+ describe 'flatten' do
1206
+ it 'does not affect colors with an alpha of 1' do
1207
+ @black.background = Color.new(:white)
1208
+ color = @black.flatten
1209
+ color.should == @black
1210
+ end
1211
+
1212
+ it 'layers the transparent color onto the background' do
1213
+ @yellow.background = @black
1214
+ color = @yellow.flatten
1215
+ layered = @black.layer(@yellow)
1216
+ color.should == layered
1217
+ end
1218
+
1219
+ it 'ignores the alpha of the background' do
1220
+ background = Color.new(:white, :alpha => 0.5)
1221
+ @yellow.background = background
1222
+ color = @yellow.flatten
1223
+
1224
+ background.alpha = 1.0
1225
+ color.should == background.layer(@yellow)
1226
+ end
1227
+ end
1228
+
1229
+ describe 'stepping' do
1230
+ before :all do
1231
+ @black = Color.new('#000')
1232
+ @yellow = Color.new(:lightyellow, :alpha => 0.5)
1233
+ @steps = @black.step(@yellow)
1234
+ end
1235
+
1236
+ it 'returs an array' do
1237
+ @steps.is_a?(Array).should be_true
1238
+ end
1239
+
1240
+ it 'has 10 steps by default' do
1241
+ @steps.size.should == 10
1242
+ end
1243
+
1244
+ it 'first color should be the starting point (dupped)' do
1245
+ @steps.first.should == @black
1246
+ @steps.first.should_not === @black
1247
+ end
1248
+
1249
+ it 'last color should be the last point (dupped)' do
1250
+ @steps.last.should == @yellow
1251
+ @steps.last.should_not === @yellow
1252
+ end
1253
+
1254
+ it 'interior steps should be equally spaced colors between the two' do
1255
+ mid = @steps[4]
1256
+ mid.r.should == @yellow.r/2.0
1257
+ mid.g.should == @yellow.g/2.0
1258
+ mid.b.should == @yellow.b/2.0
1259
+ end
1260
+
1261
+ it 'has takes optional number of steps' do
1262
+ @black.step(@yellow, 5).size.should == 5
1263
+ end
1264
+ end
1265
+ end
1266
+ end
1267
+
1268
+ describe 'rendering' do
1269
+ before do
1270
+ Color.render_as = nil
1271
+ end
1272
+
1273
+ it 'inspects' do
1274
+ color = Color.new('#000')
1275
+ color.inspect.should == "#<#{color.class}:#{color.object_id} @alpha=#{color.alpha} @r=#{color.r} @g=#{color.g} @b=#{color.b}>"
1276
+ end
1277
+
1278
+ describe 'class level render_as' do
1279
+ it 'defaults to :hex' do
1280
+ Color.render_as.should == :hex
1281
+ end
1282
+
1283
+ it 'can be set' do
1284
+ Color.render_as = :foo
1285
+ Color.render_as.should == :foo
1286
+ end
1287
+ end
1288
+
1289
+ describe '#render' do
1290
+ it 'renders to the default render_as method without transparency' do
1291
+ color = Color.new(0,0,0)
1292
+ color.render.should == '#000000'
1293
+ end
1294
+
1295
+ it 'renders as rgba if there is transparency' do
1296
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.5)
1297
+ color.render.should == "rgba(50.0%, 50.0%, 50.0%, 0.5)"
1298
+ end
1299
+
1300
+ describe 'specific render methods' do
1301
+ describe ':hex' do
1302
+ it 'will render as :hex if alpha is 1' do
1303
+ Color.render_as = :rgb
1304
+ color = Color.new(0,0,0)
1305
+ color.render(:hex).should == '#000000'
1306
+ end
1307
+
1308
+ it 'will render as :rgba if alpha is less than 1' do
1309
+ Color.render_as = :hsl
1310
+ color = Color.new(0,0,0, :alpha => 0.9)
1311
+ color.render(:hex).should == "rgba(0.0%, 0.0%, 0.0%, 0.9)"
1312
+ end
1313
+
1314
+ it 'will render as :hex if render_as is set that way' do
1315
+ Color.render_as = :hex
1316
+ color = Color.new(0,0,0)
1317
+ color.render.should == '#000000'
1318
+ end
1319
+
1320
+ it 'will render as :rgba if render_as is set that way but alpha is less than 1' do
1321
+ Color.render_as = :hex
1322
+ color = Color.new(0,0,0, :alpha => 0.9)
1323
+ color.render.should == "rgba(0.0%, 0.0%, 0.0%, 0.9)"
1324
+ end
1325
+ end
1326
+
1327
+ describe ':hsl' do
1328
+ it 'will render as :hsl from #render if the alpha is 1' do
1329
+ color = Color.new(0.5, 0.5, 0.5)
1330
+ color.set_hsl
1331
+ color.render(:hsl).should == "hsl(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%)"
1332
+ end
1333
+
1334
+ it 'will render as hsla from #render if the alpha is less than 1' do
1335
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.75)
1336
+ color.set_hsl
1337
+ color.render(:hsl).should == "hsla(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%, 0.75)"
1338
+ end
1339
+
1340
+ it "will render this way when the render_as is set to it and alpha is 1" do
1341
+ Color.render_as = :hsl
1342
+ color = Color.new(0.5, 0.5, 0.5)
1343
+ color.set_hsl
1344
+ color.render.should == "hsl(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%)"
1345
+ end
1346
+
1347
+ it 'wil render as hsla with a render_as of :hsl if the alpha is less than 1' do
1348
+ Color.render_as = :hsl
1349
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.75)
1350
+ color.set_hsl
1351
+ color.render.should == "hsla(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%, 0.75)"
1352
+ end
1353
+ end
1354
+
1355
+ describe ':hsla' do
1356
+ it 'will render as :hsla if alpha is 1' do
1357
+ color = Color.new(0.5, 0.5, 0.5)
1358
+ color.set_hsl
1359
+ color.render(:hsla).should == "hsla(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%, 1.0)"
1360
+ end
1361
+
1362
+ it 'will render as :hsla if alpha is less than 1' do
1363
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.2)
1364
+ color.set_hsl
1365
+ color.render(:hsla).should == "hsla(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%, 0.2)"
1366
+ end
1367
+
1368
+ it 'will render as :hsla when the Colol render_as is set that way' do
1369
+ Color.render_as = :hsla
1370
+ color = Color.new(0.5, 0.5, 0.5)
1371
+ color.set_hsl
1372
+ color.render.should == "hsla(#{(color.h*360).round}, #{color.s*100}%, #{color.l*100}%, 1.0)"
1373
+ end
1374
+ end
1375
+
1376
+ describe ':rgb' do
1377
+ it 'will render as :rgb from #render if the alpha is 1' do
1378
+ color = Color.new(0.5, 0.5, 0.5)
1379
+ color.render(:rgb).should == "rgb(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%)"
1380
+ end
1381
+
1382
+ it 'will render as rgba from #render if the alpha is less than 1' do
1383
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.75)
1384
+ color.render(:rgb).should == "rgba(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%, 0.75)"
1385
+ end
1386
+
1387
+ it "will render this way when the render_as is set to it and alpha is 1" do
1388
+ Color.render_as = :rgb
1389
+ color = Color.new(0.5, 0.5, 0.5)
1390
+ color.render.should == "rgb(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%)"
1391
+ end
1392
+
1393
+ it 'wil render as rgba with a render_as of :rgb if the alpha is less than 1' do
1394
+ Color.render_as = :rgb
1395
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.75)
1396
+ color.render(:rgb).should == "rgba(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%, 0.75)"
1397
+ end
1398
+ end
1399
+
1400
+ describe ':rgba' do
1401
+ it 'will render as :rgba if alpha is 1' do
1402
+ color = Color.new(0.5, 0.5, 0.5)
1403
+ color.set_rgb
1404
+ color.render(:rgba).should == "rgba(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%, 1.0)"
1405
+ end
1406
+
1407
+ it 'will render as :rgba if alpha is less than 1' do
1408
+ color = Color.new(0.5, 0.5, 0.5, :alpha => 0.2)
1409
+ color.set_rgb
1410
+ color.render(:rgba).should == "rgba(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%, 0.2)"
1411
+ end
1412
+
1413
+ it 'will render as :rgba when the Colol render_as is set that way' do
1414
+ Color.render_as = :rgba
1415
+ color = Color.new(0.5, 0.5, 0.5)
1416
+ color.set_rgb
1417
+ color.render.should == "rgba(#{color.r*100}%, #{color.g*100}%, #{color.b*100}%, 1.0)"
1418
+ end
1419
+ end
1420
+ end
1421
+
1422
+ describe 'flattened' do
1423
+ it 'will render as the render_as type when opaque' do
1424
+ Color.render_as = :hsl
1425
+ color = Color.new(:black)
1426
+ color.render(:flat).should == Color.new(:black).render_as_hsl
1427
+ end
1428
+
1429
+ it 'will flatten the color before rendering' do
1430
+ Color.render_as = :rgb
1431
+ color = Color.new(:black, :alpha => 0.5)
1432
+ color.render(:flat).should == Color.new(0.5,0.5,0.5).render_as_rgb
1433
+ end
1434
+
1435
+ it 'will render as the non-alpha type even with alhpa' do
1436
+ Color.render_as = :hex
1437
+ color = Color.new(:black, :alpha => 0.5)
1438
+ color.render(:flat).should == Color.new(0.5,0.5,0.5).render_as_hex
1439
+ end
1440
+ end
1441
+
1442
+ it 'aliases to #to_s' do
1443
+ Color.new(:black).render(:rgba).should == Color.new(:black).to_s(:rgba)
1444
+ end
1445
+ end
1446
+ end
1447
+ end