@@ -210,7 +210,7 @@ namespace Sass {
210
210
{
211
211
return sass_op_to_name (optype ());
212
212
}
213
-
213
+
214
214
const std::string Binary_Expression::separator ()
215
215
{
216
216
return sass_op_separator (optype ());
@@ -221,7 +221,7 @@ namespace Sass {
221
221
return is_left_interpolant () ||
222
222
is_right_interpolant ();
223
223
}
224
-
224
+
225
225
void Binary_Expression::set_delayed (bool delayed)
226
226
{
227
227
right ()->set_delayed (delayed);
@@ -485,24 +485,52 @@ namespace Sass {
485
485
// ///////////////////////////////////////////////////////////////////////
486
486
// ///////////////////////////////////////////////////////////////////////
487
487
488
- Color::Color (ParserState pstate, double r, double g, double b, double a, const std::string disp)
489
- : Value(pstate), r_(r), g_(g), b_(b), a_(a), disp_(disp),
488
+ Color::Color (ParserState pstate, double a, const std::string disp)
489
+ : Value(pstate),
490
+ disp_ (disp), a_(a),
490
491
hash_(0 )
491
492
{ concrete_type (COLOR); }
492
493
493
494
Color::Color (const Color* ptr)
494
- : Value(ptr),
495
- r_(ptr->r_),
496
- g_(ptr->g_),
497
- b_(ptr->b_),
495
+ : Value(ptr->pstate ()),
496
+ // reset on copy
497
+ disp_(" " ),
498
498
a_(ptr->a_),
499
- disp_(ptr->disp_),
500
499
hash_(ptr->hash_)
501
500
{ concrete_type (COLOR); }
502
501
503
502
bool Color::operator == (const Expression& rhs) const
504
503
{
505
- if (auto r = Cast<Color>(&rhs)) {
504
+ if (auto r = Cast<Color_RGBA>(&rhs)) {
505
+ return *this == *r;
506
+ }
507
+ else if (auto r = Cast<Color_HSLA>(&rhs)) {
508
+ return *this == *r;
509
+ }
510
+ else if (auto r = Cast<Color>(&rhs)) {
511
+ return a_ == r->a ();
512
+ }
513
+ return false ;
514
+ }
515
+
516
+ // ///////////////////////////////////////////////////////////////////////
517
+ // ///////////////////////////////////////////////////////////////////////
518
+
519
+ Color_RGBA::Color_RGBA (ParserState pstate, double r, double g, double b, double a, const std::string disp)
520
+ : Color(pstate, a, disp),
521
+ r_(r), g_(g), b_(b)
522
+ { concrete_type (COLOR); }
523
+
524
+ Color_RGBA::Color_RGBA (const Color_RGBA* ptr)
525
+ : Color(ptr),
526
+ r_(ptr->r_),
527
+ g_(ptr->g_),
528
+ b_(ptr->b_)
529
+ { concrete_type (COLOR); }
530
+
531
+ bool Color_RGBA::operator == (const Expression& rhs) const
532
+ {
533
+ if (auto r = Cast<Color_RGBA>(&rhs)) {
506
534
return r_ == r->r () &&
507
535
g_ == r->g () &&
508
536
b_ == r->b () &&
@@ -511,17 +539,140 @@ namespace Sass {
511
539
return false ;
512
540
}
513
541
514
- size_t Color ::hash () const
542
+ size_t Color_RGBA ::hash () const
515
543
{
516
544
if (hash_ == 0 ) {
517
- hash_ = std::hash<double >()(a_);
545
+ hash_ = std::hash<std::string>()(" RGBA" );
546
+ hash_combine (hash_, std::hash<double >()(a_));
518
547
hash_combine (hash_, std::hash<double >()(r_));
519
548
hash_combine (hash_, std::hash<double >()(g_));
520
549
hash_combine (hash_, std::hash<double >()(b_));
521
550
}
522
551
return hash_;
523
552
}
524
553
554
+ Color_HSLA_Ptr Color_RGBA::toHSLA (bool copy)
555
+ {
556
+
557
+ // Algorithm from http://en.wikipedia.org/wiki/wHSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
558
+ double r = r_ / 255.0 ;
559
+ double g = g_ / 255.0 ;
560
+ double b = b_ / 255.0 ;
561
+
562
+ double max = std::max (r, std::max (g, b));
563
+ double min = std::min (r, std::min (g, b));
564
+ double delta = max - min;
565
+
566
+ double h = 0 ;
567
+ double s;
568
+ double l = (max + min) / 2.0 ;
569
+
570
+ if (NEAR_EQUAL (max, min)) {
571
+ h = s = 0 ; // achromatic
572
+ }
573
+ else {
574
+ if (l < 0.5 ) s = delta / (max + min);
575
+ else s = delta / (2.0 - max - min);
576
+
577
+ if (r == max) h = (g - b) / delta + (g < b ? 6 : 0 );
578
+ else if (g == max) h = (b - r) / delta + 2 ;
579
+ else if (b == max) h = (r - g) / delta + 4 ;
580
+ }
581
+
582
+ // HSL hsl_struct;
583
+ h = h * 60 ;
584
+ s = s * 100 ;
585
+ l = l * 100 ;
586
+
587
+ return SASS_MEMORY_NEW (Color_HSLA,
588
+ pstate (), h, s, l, a (), " "
589
+ );
590
+ }
591
+
592
+ Color_RGBA_Ptr Color_RGBA::toRGBA (bool copy)
593
+ {
594
+ return copy ? SASS_MEMORY_COPY (this ) : this ;
595
+ }
596
+
597
+ // ///////////////////////////////////////////////////////////////////////
598
+ // ///////////////////////////////////////////////////////////////////////
599
+
600
+ Color_HSLA::Color_HSLA (ParserState pstate, double h, double s, double l, double a, const std::string disp)
601
+ : Color(pstate, a, disp),
602
+ h_ (absmod(h, 360.0 )),
603
+ s_(clip(s, 0.0 , 100.0 )),
604
+ l_(clip(l, 0.0 , 100.0 ))
605
+ // hash_(0)
606
+ { concrete_type (COLOR); }
607
+
608
+ Color_HSLA::Color_HSLA (const Color_HSLA* ptr)
609
+ : Color(ptr),
610
+ h_(ptr->h_),
611
+ s_(ptr->s_),
612
+ l_(ptr->l_)
613
+ // hash_(ptr->hash_)
614
+ { concrete_type (COLOR); }
615
+
616
+ bool Color_HSLA::operator == (const Expression& rhs) const
617
+ {
618
+ if (auto r = Cast<Color_HSLA>(&rhs)) {
619
+ return h_ == r->h () &&
620
+ s_ == r->s () &&
621
+ l_ == r->l () &&
622
+ a_ == r->a ();
623
+ }
624
+ return false ;
625
+ }
626
+
627
+ size_t Color_HSLA::hash () const
628
+ {
629
+ if (hash_ == 0 ) {
630
+ hash_ = std::hash<std::string>()(" HSLA" );
631
+ hash_combine (hash_, std::hash<double >()(a_));
632
+ hash_combine (hash_, std::hash<double >()(h_));
633
+ hash_combine (hash_, std::hash<double >()(s_));
634
+ hash_combine (hash_, std::hash<double >()(l_));
635
+ }
636
+ return hash_;
637
+ }
638
+
639
+ // hue to RGB helper function
640
+ double h_to_rgb (double m1, double m2, double h)
641
+ {
642
+ h = absmod (h, 1.0 );
643
+ if (h*6.0 < 1 ) return m1 + (m2 - m1)*h*6 ;
644
+ if (h*2.0 < 1 ) return m2;
645
+ if (h*3.0 < 2 ) return m1 + (m2 - m1) * (2.0 /3.0 - h)*6 ;
646
+ return m1;
647
+ }
648
+
649
+ Color_RGBA_Ptr Color_HSLA::toRGBA (bool copy)
650
+ {
651
+
652
+ double h = absmod (h_ / 360.0 , 1.0 );
653
+ double s = clip (s_ / 100.0 , 0.0 , 1.0 );
654
+ double l = clip (l_ / 100.0 , 0.0 , 1.0 );
655
+
656
+ // Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
657
+ double m2;
658
+ if (l <= 0.5 ) m2 = l*(s+1.0 );
659
+ else m2 = (l+s)-(l*s);
660
+ double m1 = (l*2.0 )-m2;
661
+ // round the results -- consider moving this into the Color constructor
662
+ double r = (h_to_rgb (m1, m2, h + 1.0 /3.0 ) * 255.0 );
663
+ double g = (h_to_rgb (m1, m2, h) * 255.0 );
664
+ double b = (h_to_rgb (m1, m2, h - 1.0 /3.0 ) * 255.0 );
665
+
666
+ return SASS_MEMORY_NEW (Color_RGBA,
667
+ pstate (), r, g, b, a (), " "
668
+ );
669
+ }
670
+
671
+ Color_HSLA_Ptr Color_HSLA::toHSLA (bool copy)
672
+ {
673
+ return copy ? SASS_MEMORY_COPY (this ) : this ;
674
+ }
675
+
525
676
// ///////////////////////////////////////////////////////////////////////
526
677
// ///////////////////////////////////////////////////////////////////////
527
678
@@ -796,7 +947,8 @@ namespace Sass {
796
947
IMPLEMENT_AST_OPERATORS (Function_Call);
797
948
IMPLEMENT_AST_OPERATORS (Variable);
798
949
IMPLEMENT_AST_OPERATORS (Number);
799
- IMPLEMENT_AST_OPERATORS (Color);
950
+ IMPLEMENT_AST_OPERATORS (Color_RGBA);
951
+ IMPLEMENT_AST_OPERATORS (Color_HSLA);
800
952
IMPLEMENT_AST_OPERATORS (Custom_Error);
801
953
IMPLEMENT_AST_OPERATORS (Custom_Warning);
802
954
IMPLEMENT_AST_OPERATORS (Boolean);
0 commit comments